Class: Graphiti::Query
Defined Under Namespace
Classes: RemoteSideloadResource
Constant Summary
collapse
- TRUTHY_LINKS =
[true, "true"].freeze
- LINKLESS_FORMATS =
[:json, :xml, "json", "xml"].freeze
Instance Attribute Summary collapse
Instance Method Summary
collapse
Constructor Details
#initialize(resource, params, *positional, association_name: nil, nested_include: nil, parents: [], action: nil) ⇒ Query
Returns a new instance of Query.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
# File 'lib/graphiti/query.rb', line 10
def initialize(resource, params, *positional, association_name: nil, nested_include: nil, parents: [], action: nil)
if positional.any?
Graphiti::DEPRECATOR.warn("Passing Query.new trailing arguments positionally is deprecated. Use association_name:/nested_include:/parents:/action: keywords.")
association_name ||= positional[0]
nested_include ||= positional[1]
parents = positional[2] if positional.length > 2
action ||= positional[3]
end
@resource = resource
@association_name = association_name
@params = params
@params = @params.permit! if @params.respond_to?(:permit!)
@params = @params.to_h if @params.respond_to?(:to_h)
@params = @params.deep_symbolize_keys
@include_param = nested_include || @params[:include]
@parents = parents
@action = parse_action(action)
@entity_map = Concurrent::Map.new if parents.empty?
end
|
Instance Attribute Details
Returns the value of attribute action.
8
9
10
|
# File 'lib/graphiti/query.rb', line 8
def action
@action
end
|
#association_name ⇒ Object
Returns the value of attribute association_name.
8
9
10
|
# File 'lib/graphiti/query.rb', line 8
def association_name
@association_name
end
|
Returns the value of attribute params.
8
9
10
|
# File 'lib/graphiti/query.rb', line 8
def params
@params
end
|
Returns the value of attribute resource.
8
9
10
|
# File 'lib/graphiti/query.rb', line 8
def resource
@resource
end
|
Instance Method Details
#association? ⇒ Boolean
31
32
33
|
# File 'lib/graphiti/query.rb', line 31
def association?
!!@association_name
end
|
#cache_key ⇒ Object
305
306
307
|
# File 'lib/graphiti/query.rb', line 305
def cache_key
"args-#{query_cache_key}"
end
|
#debug_requested? ⇒ Boolean
106
107
108
|
# File 'lib/graphiti/query.rb', line 106
def debug_requested?
!!@params[:debug]
end
|
#entity_map ⇒ Object
Concurrent::Map because sideload scopes resolve on pool threads
36
37
38
39
40
|
# File 'lib/graphiti/query.rb', line 36
def entity_map
return root.entity_map unless root == self
@entity_map
end
|
201
202
203
|
# File 'lib/graphiti/query.rb', line 201
def
@extra_fields ||= parse_fieldset(@params[:extra_fields] || {})
end
|
191
192
193
194
195
196
197
198
199
|
# File 'lib/graphiti/query.rb', line 191
def fields
@fields ||= begin
hash = parse_fieldset(@params[:fields] || {})
hash.each_pair do |type, fields|
hash[type] += [type] if [type]
end
hash
end
end
|
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
# File 'lib/graphiti/query.rb', line 205
def filters
@filters ||= {}.tap do |hash|
(@params[:filter] || {}).each_pair do |name, value|
name = name.to_sym
if legacy_nested?(name)
value.keys.each do |key|
filter_name = key.to_sym
filter_value = value[key]
if @resource.get_attr!(filter_name, :filterable, request: true)
hash[filter_name] = filter_value
end
end
elsif nested?(name)
name = name.to_s.split(".").last.to_sym
validate!(name, :filterable)
hash[name] = value
elsif top_level? && validate!(name, :filterable)
hash[name] = value
end
end
end
end
|
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# File 'lib/graphiti/query.rb', line 110
def hash
@hash ||= {}.tap do |h|
h[:filter] = filters
h[:sort] = sorts
h[:page] =
if association?
resource_type = @resource.class.type
h[:extra_fields] = {resource_type => [resource_type]} if .key?(resource_type)
else
h[:fields] = fields
h[:extra_fields] =
end
h[:stats] = stats
h[:include] = sideload_hash
end.reject { |_, value| value.empty? }
end
|
#include_hash ⇒ Object
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
|
# File 'lib/graphiti/query.rb', line 269
def include_hash
@include_hash ||= begin
requested = include_directive.to_hash
allowlist = nil
if @resource.context&.respond_to?(:sideload_allowlist)
allowlist = @resource.context.sideload_allowlist
allowlist = allowlist[@resource.current_action] if allowlist
end
scrubbed = allowlist ? Util::IncludeParams.scrub(requested, allowlist) : requested
scrubbed.filter do |key, value|
sideload = @resource.class.sideload(key)
sideload.nil? || sideload.readable?
end
end
end
|
#includes_requested? ⇒ Boolean
69
70
71
|
# File 'lib/graphiti/query.rb', line 69
def includes_requested?
@include_param.present?
end
|
#links_requested? ⇒ Boolean
73
74
75
76
77
|
# File 'lib/graphiti/query.rb', line 73
def links_requested?
return @links_requested if defined?(@links_requested)
@links_requested = TRUTHY_LINKS.include?(@params[:links])
end
|
#page_links? ⇒ Boolean
Also known as:
91
92
93
94
95
96
97
98
99
|
# File 'lib/graphiti/query.rb', line 91
def page_links?
if action == :find
false
elsif @resource.page_links == :on_demand
page_links_requested?
else
@resource.page_links
end
end
|
#page_links_requested? ⇒ Boolean
101
102
103
104
|
# File 'lib/graphiti/query.rb', line 101
def page_links_requested?
[@params[:page_links], @params[:pagination_links]]
.any? { |value| [true, "true"].include?(value) }
end
|
#paginate? ⇒ Boolean
301
302
303
|
# File 'lib/graphiti/query.rb', line 301
def paginate?
![false, "false"].include?(@params[:paginate])
end
|
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
|
# File 'lib/graphiti/query.rb', line 252
def
@pagination ||= {}.tap do |hash|
(@params[:page] || {}).each_pair do |name, value|
if legacy_nested?(name)
value.each_pair do |k, v|
hash[k.to_sym] = cast_page_param(k.to_sym, v)
end
elsif nested?(name)
param_name = name.to_s.split(".").last.to_sym
hash[param_name] = cast_page_param(param_name, value)
elsif top_level? && Scoping::Paginate::PARAMS.include?(name.to_sym)
hash[name.to_sym] = cast_page_param(name.to_sym, value)
end
end
end
end
|
183
184
185
|
# File 'lib/graphiti/query.rb', line 183
def parents
@parents ||= []
end
|
#render_link?(mode) ⇒ Boolean
85
86
87
88
89
|
# File 'lib/graphiti/query.rb', line 85
def render_link?(mode)
return false if suppress_links?
(mode == :on_demand) ? links_requested? : mode == true
end
|
#repeated_resource_classes ⇒ Object
Deduplication exists for a row two include paths both resolve, so a
resource class sitting at one node has nothing to collide with.
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
# File 'lib/graphiti/query.rb', line 44
def repeated_resource_classes
return root.repeated_resource_classes unless root == self
@repeated_resource_classes ||= begin
counts = Hash.new(0)
walk = [self]
while (query = walk.pop)
counts[query.resource.class] += 1
query.sideloads.each_pair do |name, sideload_query|
walk << sideload_query
sideload = query.resource.class.sideload(name)
next unless sideload.respond_to?(:children)
sideload.children.each_value { |child| counts[child.resource.class] += 2 }
end
end
counts.select { |_, count| count > 1 }.keys.to_set
end
end
|
#resource_for_sideload(sideload) ⇒ Object
146
147
148
149
150
151
152
|
# File 'lib/graphiti/query.rb', line 146
def resource_for_sideload(sideload)
if @resource.remote?
RemoteSideloadResource.new
else
sideload.resource
end
end
|
187
188
189
|
# File 'lib/graphiti/query.rb', line 187
def root
parents.first || self
end
|
#sideload_hash ⇒ Object
133
134
135
136
137
138
139
|
# File 'lib/graphiti/query.rb', line 133
def sideload_hash
@sideload_hash = {}.tap do |hash|
sideloads.each_pair do |key, value|
hash[key] = sideloads[key].hash
end
end
end
|
#sideloads ⇒ Object
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
# File 'lib/graphiti/query.rb', line 154
def sideloads
@sideloads ||= {}.tap do |hash|
include_hash.each_pair do |key, sub_hash|
sideload = @resource.class.sideload(key)
if sideload || @resource.remote?
sl_resource = resource_for_sideload(sideload)
query_parents = parents + [self]
sub_hash = sub_hash[:include] if sub_hash.key?(:include)
relationship_name = sideload ? sideload.name : key
hash[relationship_name] = Query.new sl_resource,
@params,
association_name: key,
nested_include: sub_hash,
parents: query_parents,
action: :all
else
handle_missing_sideload(key)
end
end
end
end
|
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
|
# File 'lib/graphiti/query.rb', line 230
def sorts
@sorts ||= begin
return @params[:sort] if @params[:sort].is_a?(Array)
return [] if @params[:sort].nil?
[].tap do |arr|
sort_hashes do |key, value, type|
if legacy_nested?(type)
unless @resource.remote?
@resource.get_attr!(key, :sortable, request: true)
end
arr << {key => value}
elsif !type && top_level? && validate!(key, :sortable)
arr << {key => value}
elsif nested?("#{type}.#{key}")
arr << {key => value}
end
end
end
end
end
|
288
289
290
291
292
293
294
295
296
297
298
299
|
# File 'lib/graphiti/query.rb', line 288
def stats
@stats ||= {}.tap do |hash|
(@params[:stats] || {}).each_pair do |k, v|
if legacy_nested?(k)
raise NotImplementedError.new("Association statistics are not currently supported")
elsif top_level?
v = v.split(",") if v.is_a?(String)
hash[k.to_sym] = Array(v).flatten.map(&:to_sym)
end
end
end
end
|
#suppress_links? ⇒ Boolean
79
80
81
82
83
|
# File 'lib/graphiti/query.rb', line 79
def suppress_links?
return @suppress_links if defined?(@suppress_links)
@suppress_links = LINKLESS_FORMATS.include?(params[:format])
end
|
#top_level? ⇒ Boolean
65
66
67
|
# File 'lib/graphiti/query.rb', line 65
def top_level?
!association?
end
|
#zero_results? ⇒ Boolean
127
128
129
130
131
|
# File 'lib/graphiti/query.rb', line 127
def zero_results?
!@params[:page].nil? &&
!@params[:page][:size].nil? &&
@params[:page][:size].to_i == 0
end
|