Class: Praxis::Mapper::SelectorGeneratorNode
- Inherits:
-
Object
- Object
- Praxis::Mapper::SelectorGeneratorNode
show all
- Defined in:
- lib/praxis/mapper/selector_generator.rb
Defined Under Namespace
Classes: FieldDependenciesNode
Instance Attribute Summary collapse
-
#fields_node ⇒ Object
readonly
prepend SelectorGeneratorNodeDebugger # Uncomment this to see the traces of how methods are called.
-
#model ⇒ Object
readonly
prepend SelectorGeneratorNodeDebugger # Uncomment this to see the traces of how methods are called.
-
#resource ⇒ Object
readonly
prepend SelectorGeneratorNodeDebugger # Uncomment this to see the traces of how methods are called.
-
#select ⇒ Object
readonly
prepend SelectorGeneratorNodeDebugger # Uncomment this to see the traces of how methods are called.
-
#tracks ⇒ Object
readonly
prepend SelectorGeneratorNodeDebugger # Uncomment this to see the traces of how methods are called.
Instance Method Summary
collapse
-
#add(fields) ⇒ Object
-
#add_association(name, fields) ⇒ Object
-
#add_fwding_property(name, fields) ⇒ Object
-
#add_property(name, fields) ⇒ Object
-
#add_select(name, add_field: true) ⇒ Object
-
#add_string_association(first, *rest) ⇒ Object
-
#apply_dependency(dependency, fields = true) ⇒ Object
-
#dump(mode: :columns_and_tracks) ⇒ Object
Debugging method for rspec, to easily match the desired output By default it only outputs the info related to computing columns and track dependencies.
-
#initialize(resource) ⇒ SelectorGeneratorNode
constructor
A new instance of SelectorGeneratorNode.
-
#inspect ⇒ Object
-
#map_property(name, fields, as_dependency: false) ⇒ Object
-
#merge_track(track_name, node) ⇒ Object
Constructor Details
Returns a new instance of SelectorGeneratorNode.
76
77
78
79
80
81
82
|
# File 'lib/praxis/mapper/selector_generator.rb', line 76
def initialize(resource)
@resource = resource
@select = Set.new
@select_star = false
@fields_node = FieldDependenciesNode.new(name: '/', selector_node: self)
@tracks = {}
end
|
Instance Attribute Details
#fields_node ⇒ Object
prepend SelectorGeneratorNodeDebugger # Uncomment this to see the traces of how methods are called
7
8
9
|
# File 'lib/praxis/mapper/selector_generator.rb', line 7
def fields_node
@fields_node
end
|
#model ⇒ Object
prepend SelectorGeneratorNodeDebugger # Uncomment this to see the traces of how methods are called
7
8
9
|
# File 'lib/praxis/mapper/selector_generator.rb', line 7
def model
@model
end
|
#resource ⇒ Object
prepend SelectorGeneratorNodeDebugger # Uncomment this to see the traces of how methods are called
7
8
9
|
# File 'lib/praxis/mapper/selector_generator.rb', line 7
def resource
@resource
end
|
#select ⇒ Object
prepend SelectorGeneratorNodeDebugger # Uncomment this to see the traces of how methods are called
7
8
9
|
# File 'lib/praxis/mapper/selector_generator.rb', line 7
def select
@select
end
|
#tracks ⇒ Object
prepend SelectorGeneratorNodeDebugger # Uncomment this to see the traces of how methods are called
7
8
9
|
# File 'lib/praxis/mapper/selector_generator.rb', line 7
def tracks
@tracks
end
|
Instance Method Details
#add(fields) ⇒ Object
88
89
90
91
92
93
94
|
# File 'lib/praxis/mapper/selector_generator.rb', line 88
def add(fields)
fields.each do |name, field|
fields_node.start_field(name)
map_property(name, field)
fields_node.end_field
end
end
|
#add_association(name, fields) ⇒ Object
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
# File 'lib/praxis/mapper/selector_generator.rb', line 146
def add_association(name, fields)
association = resource.model._praxis_associations.fetch(name) do
raise "missing association for #{resource} with name #{name}"
end
associated_resource = resource.model_map[association[:model]]
raise "Whoops! could not find a resource associated with model #{association[:model]} (root resource #{resource})" unless associated_resource
association[:local_key_columns].each { |col| add_select(col, add_field: false) }
node = SelectorGeneratorNode.new(associated_resource)
unless association[:remote_key_columns].empty?
fields = {} if fields == true
new_fields_as_hash = association[:remote_key_columns].each_with_object({}) do |key, hash|
hash[key] = true
end
fields = fields.merge(new_fields_as_hash)
end
node.add(fields) unless fields == true
merge_track(name, node)
node
end
|
#add_fwding_property(name, fields) ⇒ Object
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
# File 'lib/praxis/mapper/selector_generator.rb', line 182
def add_fwding_property(name, fields)
aliased_as = resource.properties[name][:as]
if aliased_as == :self
add(fields) unless fields == true
else
leaf_node = add_string_association(*aliased_as.to_s.split('.').map(&:to_sym))
leaf_node.add(fields) unless fields == true leaf_node
end
end
|
#add_property(name, fields) ⇒ Object
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
|
# File 'lib/praxis/mapper/selector_generator.rb', line 200
def add_property(name, fields)
dependencies = resource.properties[name][:dependencies]
if (praxis_compat_model = resource.model&.respond_to?(:_praxis_associations))
aliased_as = resource.properties[name][:as]
if aliased_as
if aliased_as == :self
add(fields)
else
first, *rest = aliased_as.to_s.split('.').map(&:to_sym)
extended_fields = \
if rest.empty?
fields
else
rest.reverse.inject(fields) do |accum, prop|
{ prop => accum }
end
end
add_association(first, extended_fields) if resource.model._praxis_associations[first]
end
elsif resource.model._praxis_associations[name]
add_association(name, fields)
end
end
if fields != true && resource.property_groups[name]
prefixed_fields = fields == true ? {} : fields.keys.each_with_object({}) { |k, h| h["#{name}_#{k}".to_sym] = k }
prefixed_fields.each do |prefixedname, origfieldname|
next unless dependencies.include?(prefixedname)
fields_node.start_field(origfieldname) apply_dependency(prefixedname, fields[origfieldname])
fields_node.end_field
end
else
dependencies&.each do |dependency|
if dependency == name
add_select(name) unless praxis_compat_model && resource.model._praxis_associations.key?(name)
else
apply_dependency(dependency)
end
end
end
end
|
#add_select(name, add_field: true) ⇒ Object
173
174
175
176
177
178
179
180
|
# File 'lib/praxis/mapper/selector_generator.rb', line 173
def add_select(name, add_field: true)
return @select_star = true if name == :*
return if @select_star
@fields_node.add_local_dep(name) if add_field
@select.add name
end
|
#add_string_association(first, *rest) ⇒ Object
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
# File 'lib/praxis/mapper/selector_generator.rb', line 120
def add_string_association(first, *rest)
association = resource.model._praxis_associations.fetch(first) do
raise "missing association for #{resource} with name #{first}"
end
associated_resource = resource.model_map[association[:model]]
raise "Whoops! could not find a resource associated with model #{association[:model]} (root resource #{resource})" unless associated_resource
association[:local_key_columns].each { |col| add_select(col, add_field: false) }
node = SelectorGeneratorNode.new(associated_resource)
unless association[:remote_key_columns].empty?
fields = {}
new_fields_as_hash = association[:remote_key_columns].each_with_object({}) do |key, hash|
hash[key] = true
end
fields = fields.merge(new_fields_as_hash)
end
node.add(fields) unless fields == true
leaf_node = rest.empty? ? nil : node.add_string_association(*rest)
merge_track(first, node)
leaf_node || node end
|
#apply_dependency(dependency, fields = true) ⇒ Object
255
256
257
258
259
260
261
262
263
264
265
|
# File 'lib/praxis/mapper/selector_generator.rb', line 255
def apply_dependency(dependency, fields = true)
case dependency
when Symbol
map_property(dependency, fields, as_dependency: true)
when String
head, *tail = dependency.split('.').collect(&:to_sym)
raise 'String dependencies can not be singular' if tail.nil?
add_association(head, tail.reverse.inject(true) { |hash, dep| { dep => hash } })
end
end
|
#dump(mode: :columns_and_tracks) ⇒ Object
Debugging method for rspec, to easily match the desired output By default it only outputs the info related to computing columns and track dependencies. Overriding the mode will allow to dump the model and only the field dependencies
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
|
# File 'lib/praxis/mapper/selector_generator.rb', line 286
def dump(mode: :columns_and_tracks)
hash = {}
hash[:model] = resource.model
case mode
when :columns_and_tracks
if !@select.empty? || @select_star
hash[:columns] = @select_star ? [:*] : @select.to_a
end
when :fields
dumped_fields_node = @fields_node.dump
raise "Fields node has more keys than fields!! #{dumped_fields_node}" if dumped_fields_node.keys.size > 1
hash[:fields] = dumped_fields_node[:fields] if dumped_fields_node[:fields]
else
raise "Unknown mode #{mode} for dumping SelectorGenerator"
end
hash[:tracks] = @tracks.transform_values { |v| v.dump(mode: mode) } unless @tracks.empty?
hash
end
|
#inspect ⇒ Object
84
85
86
|
# File 'lib/praxis/mapper/selector_generator.rb', line 84
def inspect
"<#{self.class}# @resource=#{@resource.name} @select=#{@select} @select_star=#{@select_star} tracking: #{@tracks.keys} (recursion omited)>"
end
|
#map_property(name, fields, as_dependency: false) ⇒ Object
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/praxis/mapper/selector_generator.rb', line 96
def map_property(name, fields, as_dependency: false)
praxis_compat_model = resource.model&.respond_to?(:_praxis_associations)
if resource.properties.key?(name)
if (target = resource.properties[name][:as])
leaf_node = add_fwding_property(name, fields)
fields_node.save_reference(leaf_node) unless target == :self
else
add_property(name, fields)
end
fields_node.add_local_dep(name)
elsif praxis_compat_model && resource.model._praxis_associations.key?(name)
add_association(name, fields)
if as_dependency
fields_node.add_local_dep(name)
else
fields_node.save_reference(tracks[name])
end
else
add_select(name)
end
end
|
#merge_track(track_name, node) ⇒ Object
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
|
# File 'lib/praxis/mapper/selector_generator.rb', line 267
def merge_track(track_name, node)
raise "Cannot merge another node for association #{track_name}: incompatible model" unless node.model == model
existing = tracks[track_name]
if existing
node.select.each do |col_name|
existing.add_select(col_name)
end
node.tracks.each do |name, n|
existing.merge_track(name, n)
end
else
tracks[track_name] = node
end
end
|