-
Notifications
You must be signed in to change notification settings - Fork 153
/
Copy pathbase.rb
138 lines (112 loc) · 3.88 KB
/
base.rb
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
# frozen_string_literal: true
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, *args, &block)
super(attribute, options, conditions).tap { |e| e.setup(*args, &block) }
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.present? ? @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