params_ready_rails5 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/arel/cte_name.rb +20 -0
- data/lib/params_ready/builder.rb +161 -0
- data/lib/params_ready/error.rb +31 -0
- data/lib/params_ready/extensions/class_reader_writer.rb +33 -0
- data/lib/params_ready/extensions/collection.rb +43 -0
- data/lib/params_ready/extensions/delegation.rb +25 -0
- data/lib/params_ready/extensions/finalizer.rb +26 -0
- data/lib/params_ready/extensions/freezer.rb +49 -0
- data/lib/params_ready/extensions/hash.rb +46 -0
- data/lib/params_ready/extensions/late_init.rb +38 -0
- data/lib/params_ready/extensions/registry.rb +44 -0
- data/lib/params_ready/extensions/undefined.rb +23 -0
- data/lib/params_ready/format.rb +132 -0
- data/lib/params_ready/helpers/arel_builder.rb +68 -0
- data/lib/params_ready/helpers/callable.rb +14 -0
- data/lib/params_ready/helpers/conditional_block.rb +31 -0
- data/lib/params_ready/helpers/find_in_hash.rb +22 -0
- data/lib/params_ready/helpers/interface_definer.rb +48 -0
- data/lib/params_ready/helpers/key_map.rb +176 -0
- data/lib/params_ready/helpers/memo.rb +41 -0
- data/lib/params_ready/helpers/options.rb +107 -0
- data/lib/params_ready/helpers/parameter_definer_class_methods.rb +39 -0
- data/lib/params_ready/helpers/parameter_storage_class_methods.rb +63 -0
- data/lib/params_ready/helpers/parameter_user_class_methods.rb +35 -0
- data/lib/params_ready/helpers/relation_builder_wrapper.rb +35 -0
- data/lib/params_ready/helpers/rule.rb +76 -0
- data/lib/params_ready/helpers/storage.rb +30 -0
- data/lib/params_ready/helpers/usage_rule.rb +36 -0
- data/lib/params_ready/input_context.rb +31 -0
- data/lib/params_ready/intent.rb +70 -0
- data/lib/params_ready/marshaller/array_marshallers.rb +132 -0
- data/lib/params_ready/marshaller/builder_module.rb +9 -0
- data/lib/params_ready/marshaller/collection.rb +165 -0
- data/lib/params_ready/marshaller/definition_module.rb +63 -0
- data/lib/params_ready/marshaller/enum_set_marshallers.rb +96 -0
- data/lib/params_ready/marshaller/parameter_module.rb +11 -0
- data/lib/params_ready/marshaller/polymorph_marshallers.rb +67 -0
- data/lib/params_ready/marshaller/struct_marshallers.rb +100 -0
- data/lib/params_ready/marshaller/tuple_marshallers.rb +103 -0
- data/lib/params_ready/ordering/column.rb +60 -0
- data/lib/params_ready/ordering/ordering.rb +276 -0
- data/lib/params_ready/output_parameters.rb +138 -0
- data/lib/params_ready/pagination/abstract_pagination.rb +18 -0
- data/lib/params_ready/pagination/cursor.rb +171 -0
- data/lib/params_ready/pagination/direction.rb +148 -0
- data/lib/params_ready/pagination/keyset_pagination.rb +254 -0
- data/lib/params_ready/pagination/keysets.rb +70 -0
- data/lib/params_ready/pagination/nulls.rb +31 -0
- data/lib/params_ready/pagination/offset_pagination.rb +130 -0
- data/lib/params_ready/pagination/tendency.rb +28 -0
- data/lib/params_ready/parameter/abstract_struct_parameter.rb +204 -0
- data/lib/params_ready/parameter/array_parameter.rb +197 -0
- data/lib/params_ready/parameter/definition.rb +272 -0
- data/lib/params_ready/parameter/enum_set_parameter.rb +102 -0
- data/lib/params_ready/parameter/parameter.rb +475 -0
- data/lib/params_ready/parameter/polymorph_parameter.rb +172 -0
- data/lib/params_ready/parameter/state.rb +132 -0
- data/lib/params_ready/parameter/struct_parameter.rb +64 -0
- data/lib/params_ready/parameter/tuple_parameter.rb +152 -0
- data/lib/params_ready/parameter/value_parameter.rb +186 -0
- data/lib/params_ready/parameter_definer.rb +14 -0
- data/lib/params_ready/parameter_user.rb +35 -0
- data/lib/params_ready/query/array_grouping.rb +68 -0
- data/lib/params_ready/query/custom_predicate.rb +102 -0
- data/lib/params_ready/query/exists_predicate.rb +103 -0
- data/lib/params_ready/query/fixed_operator_predicate.rb +77 -0
- data/lib/params_ready/query/grouping.rb +177 -0
- data/lib/params_ready/query/join_clause.rb +87 -0
- data/lib/params_ready/query/nullness_predicate.rb +71 -0
- data/lib/params_ready/query/polymorph_predicate.rb +77 -0
- data/lib/params_ready/query/predicate.rb +203 -0
- data/lib/params_ready/query/predicate_operator.rb +132 -0
- data/lib/params_ready/query/relation.rb +337 -0
- data/lib/params_ready/query/structured_grouping.rb +58 -0
- data/lib/params_ready/query/variable_operator_predicate.rb +125 -0
- data/lib/params_ready/query_context.rb +21 -0
- data/lib/params_ready/restriction.rb +252 -0
- data/lib/params_ready/result.rb +109 -0
- data/lib/params_ready/value/coder.rb +210 -0
- data/lib/params_ready/value/constraint.rb +198 -0
- data/lib/params_ready/value/custom.rb +56 -0
- data/lib/params_ready/value/validator.rb +81 -0
- data/lib/params_ready/version.rb +7 -0
- data/lib/params_ready.rb +28 -0
- metadata +227 -0
@@ -0,0 +1,337 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require_relative 'structured_grouping'
|
3
|
+
require_relative 'join_clause'
|
4
|
+
require_relative '../pagination/offset_pagination'
|
5
|
+
require_relative '../pagination/keyset_pagination'
|
6
|
+
require_relative '../pagination/direction'
|
7
|
+
require_relative '../ordering/ordering'
|
8
|
+
|
9
|
+
module ParamsReady
|
10
|
+
module Query
|
11
|
+
class Relation < StructuredGrouping
|
12
|
+
module PageAccessors
|
13
|
+
def page_accessor(name, delegate = nil)
|
14
|
+
delegate ||= "#{name}_page"
|
15
|
+
|
16
|
+
define_method name do |*args|
|
17
|
+
send(delegate, *args)&.for_frontend
|
18
|
+
end
|
19
|
+
ruby2_keywords name
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.extended(mod)
|
23
|
+
mod.page_accessor :current
|
24
|
+
mod.page_accessor :first
|
25
|
+
mod.page_accessor :last
|
26
|
+
mod.page_accessor :previous
|
27
|
+
mod.page_accessor :next
|
28
|
+
mod.page_accessor :before
|
29
|
+
mod.page_accessor :after
|
30
|
+
mod.page_accessor :limit_at, :limited_at
|
31
|
+
mod.page_accessor :toggle, :toggled_order
|
32
|
+
mod.page_accessor :reorder, :reordered
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
extend PageAccessors
|
37
|
+
extend Forwardable
|
38
|
+
|
39
|
+
def_delegators :pagination, :offset, :limit, :num_pages, :page_no, :has_previous?, :has_next?, :has_page?
|
40
|
+
|
41
|
+
def child_is_definite?(name)
|
42
|
+
return false unless definition.has_child?(name)
|
43
|
+
return false if self[name].nil?
|
44
|
+
return false unless self[name].is_definite?
|
45
|
+
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def pagination
|
50
|
+
self[:pagination]
|
51
|
+
end
|
52
|
+
|
53
|
+
def ordering
|
54
|
+
self[:ordering]
|
55
|
+
end
|
56
|
+
|
57
|
+
def ordering_or_nil
|
58
|
+
return unless child_is_definite?(:ordering)
|
59
|
+
|
60
|
+
self[:ordering]
|
61
|
+
end
|
62
|
+
|
63
|
+
def new_offset(delta)
|
64
|
+
pagination.new_offset(delta)
|
65
|
+
end
|
66
|
+
|
67
|
+
def page(delta, count: nil)
|
68
|
+
return nil unless pagination.can_yield_page?(delta, count: count)
|
69
|
+
return self if delta == 0
|
70
|
+
|
71
|
+
new_offset = pagination.new_offset(delta)
|
72
|
+
|
73
|
+
update_in(new_offset, [:pagination, 0])
|
74
|
+
end
|
75
|
+
|
76
|
+
def current_page(count: nil)
|
77
|
+
page(0, count: count)
|
78
|
+
end
|
79
|
+
|
80
|
+
def first_page
|
81
|
+
value = pagination.first_page_value
|
82
|
+
update_in(value, [:pagination])
|
83
|
+
end
|
84
|
+
|
85
|
+
def last_page(count:)
|
86
|
+
value = pagination.last_page_value(count: count)
|
87
|
+
return if value.nil?
|
88
|
+
update_in(value, [:pagination])
|
89
|
+
end
|
90
|
+
|
91
|
+
def previous_page(delta = 1)
|
92
|
+
value = pagination.previous_page_value(delta)
|
93
|
+
return if value.nil?
|
94
|
+
update_in(value, [:pagination])
|
95
|
+
end
|
96
|
+
|
97
|
+
def next_page(delta = 1, count: nil)
|
98
|
+
value = pagination.next_page_value(delta, count: count)
|
99
|
+
return if value.nil?
|
100
|
+
page(delta, count: count)
|
101
|
+
end
|
102
|
+
|
103
|
+
def before_page(keyset)
|
104
|
+
tuple = { direction: :bfr, limit: limit, keyset: keyset }
|
105
|
+
update_in(tuple, [:pagination])
|
106
|
+
end
|
107
|
+
|
108
|
+
def after_page(keyset)
|
109
|
+
tuple = { direction: :aft, limit: limit, keyset: keyset }
|
110
|
+
update_in(tuple, [:pagination])
|
111
|
+
end
|
112
|
+
|
113
|
+
def limited_at(limit)
|
114
|
+
update_in(limit, [:pagination, pagination.limit_key])
|
115
|
+
end
|
116
|
+
|
117
|
+
def toggled_order(column)
|
118
|
+
new_order = ordering.toggled_order_value(column)
|
119
|
+
toggled = update_in(new_order, [:ordering])
|
120
|
+
toggled.update_in(0, [:pagination, 0])
|
121
|
+
end
|
122
|
+
|
123
|
+
def reordered(column, direction)
|
124
|
+
new_order = ordering.reordered_value(column, direction)
|
125
|
+
reordered = update_in(new_order, [:ordering])
|
126
|
+
reordered.update_in(0, [:pagination, 0])
|
127
|
+
end
|
128
|
+
|
129
|
+
def model_class(default_model_class)
|
130
|
+
default_model_class || definition.model_class
|
131
|
+
end
|
132
|
+
|
133
|
+
def arel_table(default_model_class)
|
134
|
+
model_class(default_model_class).arel_table
|
135
|
+
end
|
136
|
+
|
137
|
+
def perform_count(scope: nil, context: Restriction.blanket_permission)
|
138
|
+
scope ||= definition.model_class if definition.model_class_defined?
|
139
|
+
group = predicate_group(scope.arel_table, context: context)
|
140
|
+
relation = scope.where(group)
|
141
|
+
relation = perform_joins(relation, context)
|
142
|
+
relation.count
|
143
|
+
end
|
144
|
+
|
145
|
+
def keysets(limit, direction, keyset, scope: nil, context: Restriction.blanket_permission, &block)
|
146
|
+
model_class = scope || definition.model_class
|
147
|
+
group = predicate_group(model_class.arel_table, context: context)
|
148
|
+
relation = model_class.where(group)
|
149
|
+
relation = perform_joins(relation, context)
|
150
|
+
|
151
|
+
sql_literal = pagination.keysets_for_relation(relation, limit, direction, keyset, ordering, context, &block)
|
152
|
+
|
153
|
+
array = model_class.connection.execute(sql_literal.to_s).to_a
|
154
|
+
Pagination::Direction.instance(direction).keysets(keyset, array, &block)
|
155
|
+
end
|
156
|
+
|
157
|
+
def build_relation(scope: nil, include: [], context: Restriction.blanket_permission, paginate: true)
|
158
|
+
model_class = scope || definition.model_class
|
159
|
+
group = predicate_group(model_class.arel_table, context: context)
|
160
|
+
relation = model_class.where(group)
|
161
|
+
relation = relation.includes(*include) unless include.empty?
|
162
|
+
relation = perform_joins(relation, context)
|
163
|
+
|
164
|
+
order_and_paginate_relation(relation, context, paginate)
|
165
|
+
end
|
166
|
+
|
167
|
+
def perform_joins(relation, context)
|
168
|
+
return relation if definition.joins.empty?
|
169
|
+
|
170
|
+
sql = joined_tables(relation.arel_table, context).join_sources.map(&:to_sql).join(' ')
|
171
|
+
relation.joins(sql)
|
172
|
+
end
|
173
|
+
|
174
|
+
def to_count(model_class: nil, context: Restriction.blanket_permission)
|
175
|
+
model_class = model_class || definition.model_class
|
176
|
+
|
177
|
+
arel_table = joined_tables(model_class.arel_table, context)
|
178
|
+
|
179
|
+
group = self.predicate_group(model_class.arel_table, context: context)
|
180
|
+
|
181
|
+
query = if group.nil?
|
182
|
+
arel_table
|
183
|
+
else
|
184
|
+
arel_table.where(group)
|
185
|
+
end
|
186
|
+
query.project(arel_table[:id].count)
|
187
|
+
end
|
188
|
+
|
189
|
+
def build_select(model_class: nil, context: Restriction.blanket_permission, select_list: Arel.star, paginate: true)
|
190
|
+
arel_table, query = build_query(model_class, context)
|
191
|
+
query = order_and_paginate_query(query, arel_table, context, paginate)
|
192
|
+
query.project(select_list)
|
193
|
+
end
|
194
|
+
|
195
|
+
def build_keyset_query(limit, direction, keyset, model_class: nil, context: Restriction.blanket_permission)
|
196
|
+
arel_table, query = build_query(model_class, context)
|
197
|
+
pagination.select_keysets(query, limit, direction, keyset, ordering, arel_table, context)
|
198
|
+
end
|
199
|
+
|
200
|
+
def build_query(model_class, context)
|
201
|
+
arel_table = arel_table(model_class)
|
202
|
+
|
203
|
+
group = self.predicate_group(arel_table, context: context)
|
204
|
+
joined = joined_tables(arel_table, context)
|
205
|
+
|
206
|
+
query = if group.nil?
|
207
|
+
joined
|
208
|
+
else
|
209
|
+
joined.where(group)
|
210
|
+
end
|
211
|
+
|
212
|
+
[arel_table, query]
|
213
|
+
end
|
214
|
+
|
215
|
+
def order_if_applicable(arel_table, context)
|
216
|
+
if child_is_definite?(:ordering) && (context.permitted?(ordering) || ordering.required?)
|
217
|
+
ordering = self.ordering.to_arel(arel_table, context: context)
|
218
|
+
yield ordering if ordering.length > 0
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def paginate_if_applicable(paginate)
|
223
|
+
if paginate && child_is_definite?(:pagination)
|
224
|
+
pagination = self.pagination
|
225
|
+
yield pagination
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def order_and_paginate_relation(relation, context, paginate)
|
230
|
+
paginate_if_applicable(paginate) do |pagination|
|
231
|
+
relation = pagination.paginate_relation(relation, ordering_or_nil, context)
|
232
|
+
end
|
233
|
+
|
234
|
+
order_if_applicable(relation.arel_table, context) do |ordering|
|
235
|
+
relation = relation.order(ordering)
|
236
|
+
end
|
237
|
+
relation
|
238
|
+
end
|
239
|
+
|
240
|
+
def order_and_paginate_query(query, arel_table, context, paginate)
|
241
|
+
paginate_if_applicable(paginate) do |pagination|
|
242
|
+
query = pagination.paginate_query(query, ordering_or_nil, arel_table, context)
|
243
|
+
end
|
244
|
+
|
245
|
+
order_if_applicable(arel_table, context) do |ordering|
|
246
|
+
query = query.order(*ordering)
|
247
|
+
end
|
248
|
+
query
|
249
|
+
end
|
250
|
+
|
251
|
+
def joined_tables(base_table, context)
|
252
|
+
definition.joins.reduce(base_table) do |joined_table, join|
|
253
|
+
join.to_arel(joined_table, base_table, context, self)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
class RelationParameterBuilder < Builder
|
259
|
+
include GroupingLike
|
260
|
+
include Parameter::AbstractStructParameterBuilder::StructLike
|
261
|
+
include HavingModel
|
262
|
+
|
263
|
+
def self.instance(name, altn: nil)
|
264
|
+
new RelationDefinition.new(name, altn: altn)
|
265
|
+
end
|
266
|
+
|
267
|
+
register :relation
|
268
|
+
DEFAULT_LIMIT = 10
|
269
|
+
|
270
|
+
def paginate(limit = DEFAULT_LIMIT, max_limit = nil, method: :offset, &block)
|
271
|
+
case method
|
272
|
+
when :offset
|
273
|
+
raise ParamsReadyError, 'Block not expected' unless block.nil?
|
274
|
+
add Pagination::OffsetPaginationDefinition.new(0, limit, max_limit).finish
|
275
|
+
when :keyset
|
276
|
+
ordering_builder = @definition.init_ordering_builder(empty: true)
|
277
|
+
rcpb = Pagination::KeysetPaginationBuilder.new ordering_builder, limit, max_limit
|
278
|
+
add rcpb.build(&block)
|
279
|
+
else
|
280
|
+
raise "Unimplemented pagination method '#{method}'"
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def order(&proc)
|
285
|
+
ordering_builder = @definition.init_ordering_builder(empty: false)
|
286
|
+
ordering_builder.instance_eval(&proc) unless proc.nil?
|
287
|
+
ordering = ordering_builder.build
|
288
|
+
add ordering
|
289
|
+
end
|
290
|
+
|
291
|
+
def join_table(arel_table, type, &block)
|
292
|
+
join = Join.new arel_table, type, &block
|
293
|
+
join.freeze
|
294
|
+
@definition.add_join(join)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
class RelationDefinition < StructuredGroupingDefinition
|
299
|
+
late_init :model_class, obligatory: false, freeze: false, getter: false
|
300
|
+
collection :joins, :join
|
301
|
+
|
302
|
+
def model_class
|
303
|
+
raise ParamsReadyError, "Model class not set for #{name}" if @model_class.nil?
|
304
|
+
@model_class
|
305
|
+
end
|
306
|
+
|
307
|
+
def init_ordering_builder(empty:)
|
308
|
+
raise ParamsReadyError, 'Ordering already defined' if empty == true && !@ordering_builder.nil?
|
309
|
+
@ordering_builder ||= Ordering::OrderingParameterBuilder.instance
|
310
|
+
end
|
311
|
+
|
312
|
+
def arel_table
|
313
|
+
model_class.arel_table
|
314
|
+
end
|
315
|
+
|
316
|
+
def model_class_defined?
|
317
|
+
!@model_class.nil?
|
318
|
+
end
|
319
|
+
|
320
|
+
attr_reader :joins
|
321
|
+
|
322
|
+
def initialize(*args, **opts)
|
323
|
+
@joins = []
|
324
|
+
@ordering_builder = nil
|
325
|
+
super
|
326
|
+
end
|
327
|
+
|
328
|
+
def finish
|
329
|
+
raise ParamsReadyError, 'Ordering must be explicitly declared' if @ordering_builder&.open?
|
330
|
+
@ordering_builder = nil
|
331
|
+
super
|
332
|
+
end
|
333
|
+
|
334
|
+
parameter_class Relation
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative '../parameter/struct_parameter'
|
2
|
+
require_relative '../parameter/value_parameter'
|
3
|
+
require_relative 'fixed_operator_predicate'
|
4
|
+
require_relative 'nullness_predicate'
|
5
|
+
require_relative 'grouping'
|
6
|
+
|
7
|
+
module ParamsReady
|
8
|
+
module Query
|
9
|
+
class StructuredGrouping < Parameter::StructParameter
|
10
|
+
include Parameter::GroupingLike
|
11
|
+
def predicates
|
12
|
+
return [] if is_nil?
|
13
|
+
|
14
|
+
definition.predicates.keys.map do |name|
|
15
|
+
parameter = child(name)
|
16
|
+
next nil unless parameter.is_definite?
|
17
|
+
parameter
|
18
|
+
end.compact
|
19
|
+
end
|
20
|
+
|
21
|
+
def operator
|
22
|
+
self[:operator].unwrap
|
23
|
+
end
|
24
|
+
|
25
|
+
def context_for_predicates(restriction)
|
26
|
+
intent_for_children(restriction)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class StructuredGroupingBuilder < Builder
|
31
|
+
include GroupingLike
|
32
|
+
include Parameter::AbstractStructParameterBuilder::StructLike
|
33
|
+
PredicateRegistry.register_predicate :structured_grouping_predicate, self
|
34
|
+
|
35
|
+
def self.instance(name, altn: nil)
|
36
|
+
new StructuredGroupingDefinition.new(name, altn: altn)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class StructuredGroupingDefinition < Parameter::StructParameterDefinition
|
41
|
+
attr_reader :arel_table, :predicates
|
42
|
+
|
43
|
+
def initialize(*args, **opts)
|
44
|
+
@predicates = {}
|
45
|
+
super *args, **opts
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_predicate(predicate)
|
49
|
+
raise ParamsReadyError, "Predicate name taken: '#{predicate.name}" if predicates.key? predicate.name
|
50
|
+
predicates[predicate.name] = predicate
|
51
|
+
end
|
52
|
+
|
53
|
+
parameter_class StructuredGrouping
|
54
|
+
|
55
|
+
freeze_variables :predicates
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require_relative 'predicate'
|
2
|
+
require_relative '../parameter/struct_parameter'
|
3
|
+
require_relative '../parameter/value_parameter'
|
4
|
+
require_relative '../value/validator'
|
5
|
+
require_relative 'predicate_operator'
|
6
|
+
|
7
|
+
module ParamsReady
|
8
|
+
module Query
|
9
|
+
class VariableOperatorPredicate < Parameter::AbstractParameter
|
10
|
+
include Predicate::DelegatingPredicate
|
11
|
+
include Predicate::HavingAttribute
|
12
|
+
|
13
|
+
def initialize(definition)
|
14
|
+
super definition
|
15
|
+
@data = definition.struct_parameter.create
|
16
|
+
end
|
17
|
+
|
18
|
+
def build_query(select_expression, context: nil)
|
19
|
+
operator.to_query(select_expression, value)
|
20
|
+
end
|
21
|
+
|
22
|
+
def perform_test(record, attribute_name)
|
23
|
+
operator.test(record, attribute_name, value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def value
|
27
|
+
@data[:value].unwrap
|
28
|
+
end
|
29
|
+
|
30
|
+
def operator
|
31
|
+
@data[:operator].unwrap
|
32
|
+
end
|
33
|
+
|
34
|
+
def inspect_content
|
35
|
+
op, val = if is_definite?
|
36
|
+
@data[:operator].unwrap_or(nil)&.name || '?'
|
37
|
+
@data[:value].unwrap_or('?')
|
38
|
+
else
|
39
|
+
%w[? ?]
|
40
|
+
end
|
41
|
+
"#{definition.attribute_name} #{op} #{val}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class OperatorCoder < Value::Coder
|
46
|
+
def self.coerce(value, context)
|
47
|
+
return value if value.class == Class && value < PredicateOperator
|
48
|
+
identifier = value.to_sym
|
49
|
+
PredicateRegistry.operator(identifier, context)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.format(value, intent)
|
53
|
+
intent.hash_key(value)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.strict_default?
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
Parameter::ValueParameterBuilder.register_coder :predicate_operator, OperatorCoder
|
62
|
+
|
63
|
+
class VariableOperatorPredicateBuilder < AbstractPredicateBuilder
|
64
|
+
PredicateRegistry.register_predicate :variable_operator_predicate, self
|
65
|
+
include HavingType
|
66
|
+
include HavingAttribute
|
67
|
+
include DelegatingBuilder[:struct_parameter_builder]
|
68
|
+
|
69
|
+
def self.instance(name, altn: nil, attr: nil)
|
70
|
+
new VariableOperatorPredicateDefinition.new name, altn: altn, attribute_name: attr
|
71
|
+
end
|
72
|
+
|
73
|
+
def data_object_handles
|
74
|
+
[:value, :val]
|
75
|
+
end
|
76
|
+
|
77
|
+
def operators(*arr, &block)
|
78
|
+
@definition.set_operators(arr, &block)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class VariableOperatorPredicateDefinition < AbstractPredicateDefinition
|
83
|
+
include HavingAttribute
|
84
|
+
|
85
|
+
attr_reader :struct_parameter_builder
|
86
|
+
attr_reader :struct_parameter
|
87
|
+
|
88
|
+
def initialize(*args, attribute_name: nil, **opts)
|
89
|
+
super *args, **opts
|
90
|
+
@attribute_name = attribute_name
|
91
|
+
@struct_parameter_builder = Builder.builder(:struct).instance(name, altn: altn)
|
92
|
+
@operator_parameter_builder = Builder.builder(:predicate_operator).instance(:operator, altn: :op)
|
93
|
+
end
|
94
|
+
|
95
|
+
def set_type(type)
|
96
|
+
@type = type
|
97
|
+
@struct_parameter_builder.add @type.finish
|
98
|
+
end
|
99
|
+
|
100
|
+
def set_operators(array, &block)
|
101
|
+
context = Format.instance(:backend)
|
102
|
+
|
103
|
+
operators = array.map do |name|
|
104
|
+
PredicateRegistry.operator(name, context)
|
105
|
+
end
|
106
|
+
@operator_parameter_builder.include do
|
107
|
+
constrain :enum, operators
|
108
|
+
end
|
109
|
+
@operator_parameter_builder.include(&block) unless block.nil?
|
110
|
+
@struct_parameter_builder.add @operator_parameter_builder.build
|
111
|
+
end
|
112
|
+
|
113
|
+
def finish
|
114
|
+
@struct_parameter = @struct_parameter_builder.build
|
115
|
+
@struct_parameter_builder = nil
|
116
|
+
@operator_parameter_builder = nil
|
117
|
+
@type = nil
|
118
|
+
|
119
|
+
super
|
120
|
+
end
|
121
|
+
|
122
|
+
parameter_class VariableOperatorPredicate
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require_relative 'restriction'
|
3
|
+
|
4
|
+
module ParamsReady
|
5
|
+
class QueryContext
|
6
|
+
include Restriction::Wrapper
|
7
|
+
extend Forwardable
|
8
|
+
attr_reader :data
|
9
|
+
def_delegator :data, :[]
|
10
|
+
|
11
|
+
def initialize(restriction, data = {})
|
12
|
+
@data = data.freeze
|
13
|
+
raise ParamsReadyError, "Restriction expected, got: #{restriction.inspect}" unless restriction.is_a? Restriction
|
14
|
+
@restriction = restriction.freeze
|
15
|
+
end
|
16
|
+
|
17
|
+
def clone(restriction:)
|
18
|
+
QueryContext.new restriction, data
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|