1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
# frozen_string_literal: true
require 'active_support'
require 'active_support/core_ext'
require 'active_support'
require 'active_support/core_ext'
module Grape
class Entity
module Exposure
class Base
attr_reader :attribute, :is_safe, :documentation, :override, :conditions, :for_merge
def self.new(attribute, options, conditions, ...)
super(attribute, options, conditions).tap { |e| e.setup(...) }
end
def initialize(attribute, options, conditions)
@attribute = attribute.try(:to_sym)
@options = options
key = options[:as] || attribute
@key = key.respond_to?(:to_sym) ? key.to_sym : key
@is_safe = options[:safe]
@default_value = options[:default]
@for_merge = options[:merge]
@attr_path_proc = options[:attr_path]
@documentation = options[:documentation]
@override = options[:override]
@conditions = conditions
end
def dup(&block)
self.class.new(*dup_args, &block)
end
def dup_args
[@attribute, @options, @conditions.map(&:dup)]
end
def ==(other)
self.class == other.class &&
@attribute == other.attribute &&
@options == other.options &&
@conditions == other.conditions
end
def setup; end
def nesting?
false
end
# if we have any nesting exposures with the same name.
def deep_complex_nesting?(entity) # rubocop:disable Lint/UnusedMethodArgument
false
end
def valid?(entity)
is_delegatable = entity.delegator.delegatable?(@attribute) || entity.respond_to?(@attribute, true)
if @is_safe
is_delegatable
else
is_delegatable || raise(
NoMethodError,
"#{entity.class.name} missing attribute `#{@attribute}' on #{entity.object}"
)
end
end
def value(_entity, _options)
raise NotImplementedError
end
def serializable_value(entity, options)
partial_output = valid_value(entity, options)
if partial_output.respond_to?(:serializable_hash)
partial_output.serializable_hash
elsif partial_output.is_a?(Array) && partial_output.all? { |o| o.respond_to?(:serializable_hash) }
partial_output.map(&:serializable_hash)
elsif partial_output.is_a?(Hash)
partial_output.each do |key, value|
partial_output[key] = value.serializable_hash if value.respond_to?(:serializable_hash)
end
else
partial_output
end
end
def valid_value(entity, options)
return unless valid?(entity)
output = value(entity, options)
output.blank? && !@default_value.nil? ? @default_value : output
end
def should_return_key?(options)
options.should_return_key?(@key)
end
def conditional?
!@conditions.empty?
end
def conditions_met?(entity, options)
@conditions.all? { |condition| condition.met? entity, options }
end
def should_expose?(entity, options)
should_return_key?(options) && conditions_met?(entity, options)
end
def attr_path(entity, options)
if @attr_path_proc
entity.exec_with_object(options, &@attr_path_proc)
else
@key
end
end
def key(entity = nil)
@key.respond_to?(:call) ? entity.exec_with_object(@options, &@key) : @key
end
def with_attr_path(entity, options, &block)
path_part = attr_path(entity, options)
options.with_attr_path(path_part, &block)
end
def override?
@override
end
protected
attr_reader :options
end
end
end
end
|