params_ready 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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:)