params_ready 0.0.7 → 0.0.8

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/params_ready/builder.rb +17 -0
  3. data/lib/params_ready/extensions/delegation.rb +1 -0
  4. data/lib/params_ready/extensions/freezer.rb +2 -0
  5. data/lib/params_ready/extensions/undefined.rb +8 -0
  6. data/lib/params_ready/helpers/arel_builder.rb +96 -35
  7. data/lib/params_ready/helpers/callable.rb +14 -0
  8. data/lib/params_ready/helpers/interface_definer.rb +48 -0
  9. data/lib/params_ready/helpers/memo.rb +0 -1
  10. data/lib/params_ready/helpers/options.rb +77 -9
  11. data/lib/params_ready/helpers/parameter_storage_class_methods.rb +27 -0
  12. data/lib/params_ready/helpers/parameter_user_class_methods.rb +18 -14
  13. data/lib/params_ready/helpers/rule.rb +30 -11
  14. data/lib/params_ready/helpers/usage_rule.rb +21 -3
  15. data/lib/params_ready/marshaller/array_marshallers.rb +4 -3
  16. data/lib/params_ready/marshaller/{hash_set_marshallers.rb → enum_set_marshallers.rb} +5 -5
  17. data/lib/params_ready/marshaller/polymorph_marshallers.rb +2 -2
  18. data/lib/params_ready/marshaller/{hash_marshallers.rb → struct_marshallers.rb} +5 -5
  19. data/lib/params_ready/marshaller/tuple_marshallers.rb +2 -2
  20. data/lib/params_ready/ordering/column.rb +1 -1
  21. data/lib/params_ready/output_parameters.rb +11 -0
  22. data/lib/params_ready/pagination/keyset_pagination.rb +5 -5
  23. data/lib/params_ready/parameter/{abstract_hash_parameter.rb → abstract_struct_parameter.rb} +5 -5
  24. data/lib/params_ready/parameter/array_parameter.rb +2 -2
  25. data/lib/params_ready/parameter/definition.rb +17 -2
  26. data/lib/params_ready/parameter/{hash_set_parameter.rb → enum_set_parameter.rb} +11 -10
  27. data/lib/params_ready/parameter/parameter.rb +25 -11
  28. data/lib/params_ready/parameter/state.rb +4 -4
  29. data/lib/params_ready/parameter/{hash_parameter.rb → struct_parameter.rb} +11 -10
  30. data/lib/params_ready/parameter/tuple_parameter.rb +1 -1
  31. data/lib/params_ready/parameter/value_parameter.rb +1 -1
  32. data/lib/params_ready/parameter_user.rb +7 -15
  33. data/lib/params_ready/query/array_grouping.rb +4 -4
  34. data/lib/params_ready/query/exists_predicate.rb +3 -3
  35. data/lib/params_ready/query/grouping.rb +8 -2
  36. data/lib/params_ready/query/join_clause.rb +91 -28
  37. data/lib/params_ready/query/predicate.rb +3 -3
  38. data/lib/params_ready/query/relation.rb +29 -14
  39. data/lib/params_ready/query/structured_grouping.rb +4 -4
  40. data/lib/params_ready/query/variable_operator_predicate.rb +10 -10
  41. data/lib/params_ready/value/coder.rb +7 -2
  42. data/lib/params_ready/version.rb +7 -0
  43. data/lib/params_ready.rb +3 -11
  44. metadata +10 -7
@@ -3,7 +3,7 @@ require_relative 'collection'
3
3
  module ParamsReady
4
4
  module Marshaller
5
5
  class PolymorphMarshallers
6
- class HashMarshaller
6
+ class StructMarshaller
7
7
  attr_reader :type_identifier
8
8
 
9
9
  def self.instance(type_identifier:)
@@ -57,7 +57,7 @@ module ParamsReady
57
57
  def self.collection
58
58
  @collection ||= begin
59
59
  c = ClassCollection.new Hash
60
- c.add_factory :hash, HashMarshaller
60
+ c.add_factory :hash, StructMarshaller
61
61
  c.freeze
62
62
  c
63
63
  end
@@ -4,7 +4,7 @@ require_relative 'collection'
4
4
 
5
5
  module ParamsReady
6
6
  module Marshaller
7
- class HashMarshallers
7
+ class StructMarshallers
8
8
  module AbstractMarshaller
9
9
  def extract_bare_value(parameter, intent)
10
10
  parameter.names.keys.reduce({}) do |result, name|
@@ -27,11 +27,11 @@ module ParamsReady
27
27
  def self.canonicalize(definition, string, context, validator)
28
28
  json = Base64.urlsafe_decode64(string)
29
29
  hash = JSON.parse(json)
30
- HashMarshaller.canonicalize(definition, hash, context, validator)
30
+ StructMarshaller.canonicalize(definition, hash, context, validator)
31
31
  end
32
32
 
33
33
  def self.marshal(parameter, intent)
34
- hash = HashMarshaller.marshal(parameter, intent)
34
+ hash = StructMarshaller.marshal(parameter, intent)
35
35
  json = JSON.generate(hash)
36
36
  Base64.urlsafe_encode64(json)
37
37
  end
@@ -39,7 +39,7 @@ module ParamsReady
39
39
  freeze
40
40
  end
41
41
 
42
- module HashMarshaller
42
+ module StructMarshaller
43
43
  extend AbstractMarshaller
44
44
 
45
45
  def self.canonicalize(definition, hash, context, validator, freeze: false)
@@ -88,7 +88,7 @@ module ParamsReady
88
88
  def self.collection
89
89
  @collection ||= begin
90
90
  c = ClassCollection.new Hash
91
- c.add_instance Hash, HashMarshaller
91
+ c.add_instance Hash, StructMarshaller
92
92
  c.add_factory :base64, Base64Marshaller
93
93
  c.default!(Hash)
94
94
  c.freeze
@@ -43,7 +43,7 @@ module ParamsReady
43
43
  freeze
44
44
  end
45
45
 
46
- module HashMarshaller
46
+ module StructMarshaller
47
47
  extend AbstractMarshaller
48
48
 
49
49
  def self.canonicalize(definition, hash, context, validator)
@@ -92,7 +92,7 @@ module ParamsReady
92
92
  @collection ||= begin
93
93
  c = ClassCollection.new Array
94
94
  c.add_instance Array, ArrayMarshaller
95
- c.add_instance Hash, HashMarshaller
95
+ c.add_instance Hash, StructMarshaller
96
96
  c.add_factory :string, StringMarshaller
97
97
  c.freeze
98
98
  c
@@ -27,7 +27,7 @@ module ParamsReady
27
27
 
28
28
  def attribute(name, default_table, context)
29
29
  arel_table = table || default_table
30
- arel_builder = Helpers::ArelBuilder.instance(expression(name), arel_table: arel_table)
30
+ arel_builder = Helpers::ArelBuilder::Attribute.instance(expression(name), arel_table: arel_table)
31
31
  arel_builder.to_arel(arel_table, context, self)
32
32
  end
33
33
 
@@ -72,6 +72,17 @@ module ParamsReady
72
72
  end
73
73
  end
74
74
 
75
+
76
+ def to_a
77
+ if @parameter.definition.is_a? Parameter::ArrayParameterDefinition
78
+ (0...@parameter.length).map do |n|
79
+ self[n]
80
+ end
81
+ else
82
+ raise ParamsReadyError, "Unimplemented method 'to_a' for #{@parameter.definition.class.name}"
83
+ end
84
+ end
85
+
75
86
  def flat_pairs(format = @intent.format, restriction: @intent.restriction, data: @intent.data)
76
87
  self.class.flatten_hash(for_output(format, restriction: restriction, data: data), scoped_name)
77
88
  end
@@ -1,4 +1,4 @@
1
- require_relative '../parameter/hash_parameter'
1
+ require_relative '../parameter/struct_parameter'
2
2
  require_relative '../value/constraint'
3
3
  require_relative '../helpers/arel_builder'
4
4
  require_relative 'abstract_pagination'
@@ -6,7 +6,7 @@ require_relative 'direction'
6
6
 
7
7
  module ParamsReady
8
8
  module Pagination
9
- class KeysetPagination < Parameter::HashParameter
9
+ class KeysetPagination < Parameter::StructParameter
10
10
  include AbstractPagination
11
11
 
12
12
  def select_keysets(query, limit, direction, keyset, ordering, arel_table, context)
@@ -177,7 +177,7 @@ module ParamsReady
177
177
  end
178
178
  end
179
179
 
180
- class KeysetPaginationDefinition < Parameter::HashParameterDefinition
180
+ class KeysetPaginationDefinition < Parameter::StructParameterDefinition
181
181
  MIN_LIMIT = 1
182
182
 
183
183
  parameter_class KeysetPagination
@@ -212,14 +212,14 @@ module ParamsReady
212
212
  class KeysetPaginationBuilder
213
213
  def initialize(ordering_builder, default_limit, max_limit = nil)
214
214
  definition = KeysetPaginationDefinition.new(default_limit, max_limit)
215
- @cursor_builder = Parameter::HashParameterBuilder.send :new, definition
215
+ @cursor_builder = Parameter::StructParameterBuilder.send :new, definition
216
216
  @default = {
217
217
  limit: default_limit,
218
218
  direction: :aft,
219
219
  keyset: {}
220
220
  }
221
221
  @ordering_builder = ordering_builder
222
- @keyset = Parameter::HashParameterBuilder.instance(:keyset, altn: :ks)
222
+ @keyset = Parameter::StructParameterBuilder.instance(:keyset, altn: :ks)
223
223
  end
224
224
 
225
225
  def key(type, name, direction, &block)
@@ -1,6 +1,6 @@
1
1
  require_relative 'parameter'
2
2
  require_relative '../helpers/key_map'
3
- require_relative '../marshaller/hash_marshallers'
3
+ require_relative '../marshaller/struct_marshallers'
4
4
  require_relative '../marshaller/builder_module'
5
5
  require_relative '../marshaller/definition_module'
6
6
 
@@ -8,7 +8,7 @@ module ParamsReady
8
8
  module Parameter
9
9
  using Extensions::Hash
10
10
 
11
- class AbstractHashParameter < Parameter
11
+ class AbstractStructParameter < Parameter
12
12
  include ComplexParameter
13
13
 
14
14
  def_delegators :@definition, :names, :remap?
@@ -132,10 +132,10 @@ module ParamsReady
132
132
  end
133
133
  end
134
134
 
135
- module AbstractHashParameterBuilder
135
+ module AbstractStructParameterBuilder
136
136
  include Marshaller::BuilderModule
137
137
 
138
- module HashLike
138
+ module StructLike
139
139
  def add(input, *args, **opts, &block)
140
140
  definition = self.class.resolve(input, *args, **opts, &block)
141
141
  @definition.add_child definition
@@ -143,7 +143,7 @@ module ParamsReady
143
143
  end
144
144
  end
145
145
 
146
- class AbstractHashParameterDefinition < Definition
146
+ class AbstractStructParameterDefinition < Definition
147
147
  attr_reader :key_map
148
148
 
149
149
  def duplicate_value(value)
@@ -1,6 +1,6 @@
1
1
  require_relative 'parameter'
2
2
  require_relative 'definition'
3
- require_relative 'abstract_hash_parameter'
3
+ require_relative 'abstract_struct_parameter'
4
4
  require_relative '../builder'
5
5
  require_relative '../marshaller/array_marshallers'
6
6
  require_relative '../marshaller/builder_module'
@@ -74,7 +74,7 @@ module ParamsReady
74
74
  end
75
75
 
76
76
  def_delegators :@definition, :prototype
77
- def_delegators :bare_value, :length, :each, :each_with_index, :map, :reduce, :to_a
77
+ def_delegators :bare_value, :length, :count, :each, :each_with_index, :map, :reduce, :to_a
78
78
 
79
79
  freeze_variable :value do |array|
80
80
  array.each(&:freeze)
@@ -9,6 +9,7 @@ require_relative '../extensions/undefined'
9
9
  require_relative '../input_context'
10
10
  require_relative '../result'
11
11
  require_relative '../helpers/conditional_block'
12
+ require_relative '../helpers/callable'
12
13
 
13
14
  module ParamsReady
14
15
  module Parameter
@@ -212,6 +213,7 @@ module ParamsReady
212
213
 
213
214
  late_init :default, once: false, definite: false do |value|
214
215
  next value if value == Extensions::Undefined
216
+ next value if value.is_a? Helpers::Callable
215
217
 
216
218
  canonical = canonical_default(value)
217
219
  next canonical if canonical.nil?
@@ -219,11 +221,24 @@ module ParamsReady
219
221
  freeze_value(canonical)
220
222
  end
221
223
 
222
- def duplicate_default
224
+ def fetch_default(duplicate: true)
223
225
  return Extensions::Undefined unless default_defined?
224
226
  return nil if @default.nil?
225
227
 
226
- duplicate_value(@default)
228
+ if @default.is_a?(Helpers::Callable)
229
+ fetch_callable_default
230
+ else
231
+ return @default unless duplicate
232
+ duplicate_value(@default)
233
+ end
234
+ end
235
+
236
+ def fetch_callable_default
237
+ value = @default.call
238
+ value = ensure_canonical(value)
239
+ duplicate_value(value)
240
+ rescue StandardError => e
241
+ raise ParamsReadyError, "Invalid default: #{e.message}"
227
242
  end
228
243
 
229
244
 
@@ -1,13 +1,13 @@
1
1
  require 'set'
2
- require_relative 'hash_parameter'
2
+ require_relative 'struct_parameter'
3
3
  require_relative 'value_parameter'
4
4
  require_relative '../intent'
5
- require_relative '../marshaller/hash_set_marshallers'
5
+ require_relative '../marshaller/enum_set_marshallers'
6
6
  require_relative '../marshaller/parameter_module'
7
7
 
8
8
  module ParamsReady
9
9
  module Parameter
10
- class HashSetParameter < AbstractHashParameter
10
+ class EnumSetParameter < AbstractStructParameter
11
11
  include Marshaller::ParameterModule
12
12
 
13
13
  def self.intent_for_set(intent)
@@ -31,13 +31,14 @@ module ParamsReady
31
31
  end
32
32
  end
33
33
 
34
- class HashSetParameterBuilder < Builder
34
+ class EnumSetParameterBuilder < Builder
35
35
  include Marshaller::BuilderModule
36
36
 
37
- register :hash_set
37
+ register :enum_set
38
+ register_deprecated :hash_set, use: :enum_set
38
39
 
39
40
  def self.instance(name, altn: nil, type: :boolean)
40
- new HashSetParameterDefinition.new(name, altn: altn, type: type)
41
+ new EnumSetParameterDefinition.new(name, altn: altn, type: type)
41
42
  end
42
43
 
43
44
  def add(input, *args, val: nil, **opts, &block)
@@ -56,12 +57,12 @@ module ParamsReady
56
57
  end
57
58
  end
58
59
 
59
- class HashSetParameterDefinition < AbstractHashParameterDefinition
60
+ class EnumSetParameterDefinition < AbstractStructParameterDefinition
60
61
  attr_reader :type, :values
61
62
  freeze_variable :values
62
- name_for_formatter :hash_set
63
- parameter_class HashSetParameter
64
- include Marshaller::DefinitionModule[Marshaller::HashSetMarshallers.collection]
63
+ name_for_formatter :enum_set
64
+ parameter_class EnumSetParameter
65
+ include Marshaller::DefinitionModule[Marshaller::EnumSetMarshallers.collection]
65
66
 
66
67
  def initialize(*args, type: :boolean, **opts)
67
68
  @type = type
@@ -347,14 +347,18 @@ module ParamsReady
347
347
  format(Intent.instance(:backend))
348
348
  end
349
349
 
350
- def unwrap_or(default)
350
+ def unwrap_or(*args, &block)
351
+ ensure_default_present!(*args, &block)
352
+
351
353
  if is_definite?
352
- unwrap
354
+ begin
355
+ unwrap
356
+ rescue StandardError => _
357
+ supply_default(*args, &block)
358
+ end
353
359
  else
354
- default
360
+ supply_default(*args, &block)
355
361
  end
356
- rescue StandardError => _
357
- default
358
362
  end
359
363
 
360
364
  def find_in_hash(hash, context)
@@ -432,22 +436,32 @@ module ParamsReady
432
436
  nil
433
437
  end
434
438
 
439
+ def ensure_default_present!(*args, &block)
440
+ raise ParamsReadyError, 'Single default value expected' if args.length > 1
441
+ raise ParamsReadyError, 'Supply either default or a block' if args.length == 0 && block.nil?
442
+ warn 'WARNING: block supersedes default value' if args.length > 0 && block
443
+ end
444
+
445
+ def supply_default(*args, &block)
446
+ if block.nil?
447
+ args[0]
448
+ else
449
+ block.call
450
+ end
451
+ end
452
+
435
453
  def init_for_read(to_be_frozen = false)
436
454
  return unless @value == Extensions::Undefined
437
455
  return unless default_defined?
438
456
 
439
- @value = if to_be_frozen
440
- definition.default
441
- else
442
- definition.duplicate_default
443
- end
457
+ @value = definition.fetch_default(duplicate: !to_be_frozen)
444
458
  end
445
459
 
446
460
  def init_for_write
447
461
  return if is_definite?
448
462
 
449
463
  if default_defined? && !default.nil?
450
- @value = definition.duplicate_default
464
+ @value = definition.fetch_default
451
465
  else
452
466
  init_value
453
467
  end
@@ -1,10 +1,10 @@
1
1
  require_relative '../error'
2
- require_relative '../../params_ready/parameter/hash_parameter'
2
+ require_relative '../../params_ready/parameter/struct_parameter'
3
3
  require_relative '../query/relation'
4
4
 
5
5
  module ParamsReady
6
6
  module Parameter
7
- class State < HashParameter
7
+ class State < StructParameter
8
8
  extend Query::Relation::PageAccessors
9
9
  extend Forwardable
10
10
  def_delegators :definition, :relations
@@ -98,7 +98,7 @@ module ParamsReady
98
98
  end
99
99
  end
100
100
 
101
- class StateBuilder < HashParameterBuilder
101
+ class StateBuilder < StructParameterBuilder
102
102
  def relation(relation)
103
103
  @definition.add_relation relation
104
104
  end
@@ -109,7 +109,7 @@ module ParamsReady
109
109
  end
110
110
  end
111
111
 
112
- class StateDefinition < HashParameterDefinition
112
+ class StateDefinition < StructParameterDefinition
113
113
  parameter_class State
114
114
  attr_reader :relations
115
115
 
@@ -1,22 +1,23 @@
1
1
  require_relative 'parameter'
2
2
  require_relative '../builder'
3
- require_relative 'abstract_hash_parameter'
3
+ require_relative 'abstract_struct_parameter'
4
4
  require_relative '../marshaller/parameter_module'
5
5
 
6
6
 
7
7
  module ParamsReady
8
8
  module Parameter
9
- class HashParameter < AbstractHashParameter
9
+ class StructParameter < AbstractStructParameter
10
10
  include Marshaller::ParameterModule
11
11
  end
12
12
 
13
- class HashParameterBuilder < Builder
14
- include AbstractHashParameterBuilder::HashLike
13
+ class StructParameterBuilder < Builder
14
+ include AbstractStructParameterBuilder::StructLike
15
15
  include Marshaller::BuilderModule
16
- register :hash
16
+ register :struct
17
+ register_deprecated :hash, use: :struct
17
18
 
18
19
  def self.instance(name, altn: nil)
19
- new HashParameterDefinition.new(name, altn: altn)
20
+ new StructParameterDefinition.new(name, altn: altn)
20
21
  end
21
22
 
22
23
  def map(hash)
@@ -24,11 +25,11 @@ module ParamsReady
24
25
  end
25
26
  end
26
27
 
27
- class HashParameterDefinition < AbstractHashParameterDefinition
28
- include Marshaller::DefinitionModule[Marshaller::HashMarshallers.collection]
28
+ class StructParameterDefinition < AbstractStructParameterDefinition
29
+ include Marshaller::DefinitionModule[Marshaller::StructMarshallers.collection]
29
30
 
30
- name_for_formatter :hash
31
- parameter_class HashParameter
31
+ name_for_formatter :struct
32
+ parameter_class StructParameter
32
33
  freeze_variables :key_map
33
34
 
34
35
  def ensure_canonical(hash)
@@ -98,7 +98,7 @@ module ParamsReady
98
98
  end
99
99
  end
100
100
 
101
- class HashMarshaller
101
+ class StructMarshaller
102
102
  def marshal(fields, _format)
103
103
  fields.each_with_index.map do |field, index|
104
104
  [index.to_s, field]
@@ -165,7 +165,7 @@ module ParamsReady
165
165
  def ensure_canonical(value)
166
166
  coerced = coder.try_coerce value, Format.instance(:backend)
167
167
  if coder.strict_default? && value != coerced
168
- raise ParamsReadyError, "input '#{value}' (#{value.class.name}) coerced to '#{coerced}' (#{coerced.class.name})"
168
+ raise ParamsReadyError, "input '#{value}'/#{value.class.name} (expected '#{coerced}'/#{coerced.class.name})"
169
169
  end
170
170
  validate coerced
171
171
  coerced
@@ -15,29 +15,21 @@ module ParamsReady
15
15
  protected
16
16
 
17
17
  def parameter_definition(key)
18
- self.class.parameter_definition key
18
+ self.class.parameter_definition key
19
19
  end
20
20
 
21
21
  def relation_definition(key)
22
- self.class.relation_definition key
22
+ self.class.relation_definition key
23
23
  end
24
24
 
25
- def populate_state_for(method, params, context = Format.instance(:frontend), validator = nil)
26
- definition = create_state_for method
25
+ def populate_state_for(key, params, context = Format.instance(:frontend), validator = nil)
26
+ definition = create_state_for key
27
27
  result, state = definition.from_input(params || {}, context: context, validator: validator || Result.new(:params_ready))
28
28
  [result, state]
29
29
  end
30
30
 
31
- def create_state_for(method)
32
- builder = Parameter::StateBuilder.instance
33
- options = self.class.params_ready_storage
34
- options.parameter_rules do |rule|
35
- builder.add rule.parameter_definition if rule.valid_for(method)
36
- end
37
- options.relation_rules do |rule|
38
- builder.relation rule.parameter_definition if rule.valid_for(method)
39
- end
40
- builder.build
31
+ def create_state_for(key)
32
+ self.class.params_ready_option.create_state_for(key)
41
33
  end
42
34
  end
43
- end
35
+ end
@@ -1,11 +1,11 @@
1
- require_relative '../parameter/hash_parameter'
1
+ require_relative '../parameter/struct_parameter'
2
2
  require_relative '../parameter/array_parameter'
3
3
  require_relative 'grouping'
4
4
  require_relative 'predicate'
5
5
 
6
6
  module ParamsReady
7
7
  module Query
8
- class ArrayGrouping < Parameter::HashParameter
8
+ class ArrayGrouping < Parameter::StructParameter
9
9
  include Parameter::GroupingLike
10
10
 
11
11
  def predicates
@@ -29,7 +29,7 @@ module ParamsReady
29
29
  end
30
30
 
31
31
  class ArrayGroupingBuilder < Builder
32
- include Parameter::AbstractHashParameterBuilder::HashLike
32
+ include Parameter::AbstractStructParameterBuilder::StructLike
33
33
  PredicateRegistry.register_predicate :array_grouping_predicate, self
34
34
 
35
35
  def prototype(type_name, name = :proto, *arr, **opts, &block)
@@ -48,7 +48,7 @@ module ParamsReady
48
48
  end
49
49
  end
50
50
 
51
- class ArrayGroupingDefinition < Parameter::HashParameterDefinition
51
+ class ArrayGroupingDefinition < Parameter::StructParameterDefinition
52
52
  def initialize(*args, **opts)
53
53
  super
54
54
  end
@@ -58,7 +58,7 @@ module ParamsReady
58
58
  PredicateRegistry.register_predicate :exists_predicate, self
59
59
 
60
60
  include GroupingLike
61
- include Parameter::AbstractHashParameterBuilder::HashLike
61
+ include Parameter::AbstractStructParameterBuilder::StructLike
62
62
  include HavingArelTable
63
63
 
64
64
  def self.instance(name, altn: nil, coll: nil)
@@ -66,8 +66,8 @@ module ParamsReady
66
66
  end
67
67
 
68
68
  def related(on: nil, eq: nil, &block)
69
- join_statement = JoinStatement.new(on: on, eq: eq, &block)
70
- @definition.set_related(join_statement)
69
+ join_statement = JoinStatement::Builder.new(on: on, eq: eq, &block)
70
+ @definition.set_related(join_statement.build)
71
71
  end
72
72
 
73
73
  def outer_table(arel_table)
@@ -48,6 +48,10 @@ module ParamsReady
48
48
  definition = Builder.define_grouping_operator(:operator, altn: :op, &block)
49
49
  add definition
50
50
  end
51
+
52
+ def to_query?(&block)
53
+ helper :to_query?, &block
54
+ end
51
55
  end
52
56
  end
53
57
 
@@ -67,10 +71,12 @@ module ParamsReady
67
71
  arel_table.grouping(subqueries)
68
72
  end
69
73
 
70
- def eligible_for_query?(_table, context)
74
+ def eligible_for_query?(table, context)
71
75
  return false unless context.permitted? self
76
+ return false unless is_definite?
77
+ return true unless respond_to?(:to_query?)
72
78
 
73
- is_definite?
79
+ to_query?(table, context)
74
80
  end
75
81
 
76
82
  def to_query_if_eligible(arel_table, context:)