params_ready 0.0.1
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.rb +36 -0
- data/lib/params_ready/builder.rb +140 -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 +15 -0
- data/lib/params_ready/format.rb +130 -0
- data/lib/params_ready/helpers/arel_builder.rb +68 -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/key_map.rb +176 -0
- data/lib/params_ready/helpers/memo.rb +42 -0
- data/lib/params_ready/helpers/options.rb +39 -0
- data/lib/params_ready/helpers/parameter_definer_class_methods.rb +39 -0
- data/lib/params_ready/helpers/parameter_storage_class_methods.rb +36 -0
- data/lib/params_ready/helpers/parameter_user_class_methods.rb +31 -0
- data/lib/params_ready/helpers/relation_builder_wrapper.rb +35 -0
- data/lib/params_ready/helpers/rule.rb +57 -0
- data/lib/params_ready/helpers/storage.rb +30 -0
- data/lib/params_ready/helpers/usage_rule.rb +18 -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/hash_marshallers.rb +100 -0
- data/lib/params_ready/marshaller/hash_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/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 +127 -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_hash_parameter.rb +204 -0
- data/lib/params_ready/parameter/array_parameter.rb +197 -0
- data/lib/params_ready/parameter/definition.rb +264 -0
- data/lib/params_ready/parameter/hash_parameter.rb +63 -0
- data/lib/params_ready/parameter/hash_set_parameter.rb +101 -0
- data/lib/params_ready/parameter/parameter.rb +456 -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/tuple_parameter.rb +152 -0
- data/lib/params_ready/parameter/value_parameter.rb +182 -0
- data/lib/params_ready/parameter_definer.rb +14 -0
- data/lib/params_ready/parameter_user.rb +43 -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 +181 -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 +68 -0
- metadata +181 -0
@@ -0,0 +1,182 @@
|
|
1
|
+
require_relative 'parameter'
|
2
|
+
require_relative '../value/validator'
|
3
|
+
require_relative '../value/coder'
|
4
|
+
require_relative 'definition'
|
5
|
+
require_relative '../builder'
|
6
|
+
|
7
|
+
module ParamsReady
|
8
|
+
module Parameter
|
9
|
+
class ValueParameter < Parameter
|
10
|
+
def_delegators :@definition, :coder
|
11
|
+
|
12
|
+
def marshal(intent)
|
13
|
+
return nil if is_nil?
|
14
|
+
|
15
|
+
value = bare_value
|
16
|
+
return value unless intent.marshal?(name_for_formatter)
|
17
|
+
|
18
|
+
coder.format(value, intent)
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def update_self(value)
|
24
|
+
clone = dup
|
25
|
+
clone.set_value value
|
26
|
+
|
27
|
+
if frozen?
|
28
|
+
if clone == self
|
29
|
+
return false, self
|
30
|
+
else
|
31
|
+
[true, clone.freeze]
|
32
|
+
end
|
33
|
+
else
|
34
|
+
[true, clone]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def populate_with(value)
|
39
|
+
@value = value.dup
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class ValueParameterBuilder < Builder
|
44
|
+
module ValueLike
|
45
|
+
def constrain(name_or_constraint, *args, strategy: :raise, **opts, &block)
|
46
|
+
validator = Value::Validator.instance(name_or_constraint, *args, strategy: strategy, **opts, &block)
|
47
|
+
@definition.add_constraint validator
|
48
|
+
end
|
49
|
+
|
50
|
+
def coerce(&block)
|
51
|
+
@definition.set_coerce(block)
|
52
|
+
end
|
53
|
+
|
54
|
+
def format(&block)
|
55
|
+
@definition.set_format(block)
|
56
|
+
end
|
57
|
+
|
58
|
+
def type_identifier(name)
|
59
|
+
@definition.set_type_identifier(name)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
include ValueLike
|
64
|
+
extend Extensions::Registry
|
65
|
+
|
66
|
+
register :value
|
67
|
+
|
68
|
+
registry :coders, as: :coder, getter: true do |name, _|
|
69
|
+
builder_class = ValueParameterBuilder[name]
|
70
|
+
builder_class.register name
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.instance(name, coder_or_name = nil, altn: nil)
|
74
|
+
coder = if coder_or_name.is_a? Symbol
|
75
|
+
self.coder(coder_or_name)
|
76
|
+
elsif coder_or_name.nil?
|
77
|
+
Value::GenericCoder.new(name)
|
78
|
+
else
|
79
|
+
coder_or_name
|
80
|
+
end
|
81
|
+
new ValueParameterDefinition.new(name, coder, altn: altn)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.[](type)
|
85
|
+
builder = Class.new(self)
|
86
|
+
capitalized = type.to_s.split('_').map(&:capitalize).join
|
87
|
+
qualified = "#{self.name}::#{capitalized}Builder".freeze
|
88
|
+
|
89
|
+
builder.define_singleton_method :name do
|
90
|
+
qualified
|
91
|
+
end
|
92
|
+
|
93
|
+
builder.define_singleton_method :instance do |name, altn: nil|
|
94
|
+
superclass.instance(name, type, altn: altn)
|
95
|
+
end
|
96
|
+
|
97
|
+
builder
|
98
|
+
end
|
99
|
+
|
100
|
+
register_coder :integer, Value::IntegerCoder
|
101
|
+
register_coder :decimal, Value::DecimalCoder
|
102
|
+
register_coder :string, Value::StringCoder
|
103
|
+
register_coder :symbol, Value::SymbolCoder
|
104
|
+
register_coder :boolean, Value::BooleanCoder
|
105
|
+
register_coder :date, Value::DateCoder
|
106
|
+
register_coder :datetime, Value::DateTimeCoder
|
107
|
+
end
|
108
|
+
|
109
|
+
class ValueParameterDefinition < Definition
|
110
|
+
extend Forwardable
|
111
|
+
def_delegators :@coder, :set_coerce, :set_format, :set_type_identifier
|
112
|
+
|
113
|
+
name_for_formatter :value
|
114
|
+
|
115
|
+
def name_for_formatter
|
116
|
+
coder_name = @coder.type_identifier
|
117
|
+
return coder_name unless coder_name.nil?
|
118
|
+
|
119
|
+
super
|
120
|
+
end
|
121
|
+
|
122
|
+
parameter_class ValueParameter
|
123
|
+
|
124
|
+
module ValueLike
|
125
|
+
def duplicate_value(value)
|
126
|
+
value.dup
|
127
|
+
end
|
128
|
+
|
129
|
+
def freeze_value(value)
|
130
|
+
value.freeze
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
include ValueLike
|
135
|
+
|
136
|
+
attr_reader :coder
|
137
|
+
|
138
|
+
collection :constraints, :constraint do |constraint|
|
139
|
+
raise ParamsReadyError, "Can't constrain after default has been set" if default_defined?
|
140
|
+
constraint
|
141
|
+
end
|
142
|
+
|
143
|
+
def initialize(name, coder, *args, constraints: [], **options)
|
144
|
+
@coder = coder
|
145
|
+
@constraints = constraints
|
146
|
+
super name, *args, **options
|
147
|
+
end
|
148
|
+
|
149
|
+
def try_canonicalize(input, context, validator = nil)
|
150
|
+
value = coder.try_coerce input, context
|
151
|
+
return value if Extensions::Undefined.value_indefinite?(value)
|
152
|
+
|
153
|
+
value, validator = validate value, validator
|
154
|
+
if validator.nil? || validator.ok?
|
155
|
+
[value.freeze, validator]
|
156
|
+
else
|
157
|
+
[nil, validator]
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def ensure_canonical(value)
|
162
|
+
coerced = coder.try_coerce value, Format.instance(:backend)
|
163
|
+
if coder.strict_default? && value != coerced
|
164
|
+
raise ParamsReadyError, "input '#{value}' (#{value.class.name}) coerced to '#{coerced}' (#{coerced.class.name})"
|
165
|
+
end
|
166
|
+
validate coerced
|
167
|
+
coerced
|
168
|
+
end
|
169
|
+
|
170
|
+
def validate(value, validator = nil)
|
171
|
+
constraints.reduce([value, validator]) do |(value, validator), constraint|
|
172
|
+
constraint.validate value, validator
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def finish
|
177
|
+
@coder.finish if @coder.respond_to?(:finish)
|
178
|
+
super
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'helpers/parameter_definer_class_methods'
|
2
|
+
require_relative 'helpers/parameter_storage_class_methods'
|
3
|
+
require_relative 'helpers/relation_builder_wrapper'
|
4
|
+
|
5
|
+
module ParamsReady
|
6
|
+
module ParameterDefiner
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(Helpers::ParameterStorageClassMethods)
|
9
|
+
base.extend(Helpers::ParameterDefinerClassMethods)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative 'result'
|
2
|
+
require_relative 'helpers/usage_rule'
|
3
|
+
require_relative 'helpers/options'
|
4
|
+
require_relative 'helpers/parameter_user_class_methods'
|
5
|
+
require_relative 'helpers/parameter_storage_class_methods'
|
6
|
+
require_relative 'parameter/state'
|
7
|
+
|
8
|
+
module ParamsReady
|
9
|
+
module ParameterUser
|
10
|
+
def self.included(base)
|
11
|
+
base.extend(Helpers::ParameterStorageClassMethods)
|
12
|
+
base.extend(Helpers::ParameterUserClassMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def parameter_definition(key)
|
18
|
+
self.class.parameter_definition key
|
19
|
+
end
|
20
|
+
|
21
|
+
def relation_definition(key)
|
22
|
+
self.class.relation_definition key
|
23
|
+
end
|
24
|
+
|
25
|
+
def populate_state_for(method, params, context = Format.instance(:frontend), validator = nil)
|
26
|
+
definition = create_state_for method
|
27
|
+
result, state = definition.from_input(params || {}, context: context, validator: validator || Result.new(:params_ready))
|
28
|
+
[result, state]
|
29
|
+
end
|
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
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require_relative '../parameter/hash_parameter'
|
2
|
+
require_relative '../parameter/array_parameter'
|
3
|
+
require_relative 'grouping'
|
4
|
+
require_relative 'predicate'
|
5
|
+
|
6
|
+
module ParamsReady
|
7
|
+
module Query
|
8
|
+
class ArrayGrouping < Parameter::HashParameter
|
9
|
+
include Parameter::GroupingLike
|
10
|
+
|
11
|
+
def predicates
|
12
|
+
self[:array].to_a
|
13
|
+
end
|
14
|
+
|
15
|
+
def operator
|
16
|
+
self[:operator].unwrap
|
17
|
+
end
|
18
|
+
|
19
|
+
def context_for_predicates(restriction)
|
20
|
+
restriction.for_children(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_query(arel_table, context: Restriction.blanket_permission)
|
24
|
+
array = self[:array]
|
25
|
+
|
26
|
+
context = array.intent_for_children(context)
|
27
|
+
super arel_table, context: context
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class ArrayGroupingBuilder < Builder
|
32
|
+
include Parameter::AbstractHashParameterBuilder::HashLike
|
33
|
+
PredicateRegistry.register_predicate :array_grouping_predicate, self
|
34
|
+
|
35
|
+
def prototype(type_name, name = :proto, *arr, **opts, &block)
|
36
|
+
prototype = PredicateRegistry.predicate(type_name).instance(name, *arr, **opts)
|
37
|
+
prototype.instance_eval(&block) unless block.nil?
|
38
|
+
@definition.set_prototype prototype.build
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.instance(name, altn: nil)
|
42
|
+
new ArrayGroupingDefinition.new(name, altn: altn)
|
43
|
+
end
|
44
|
+
|
45
|
+
def operator(&block)
|
46
|
+
definition = Builder.define_grouping_operator(:operator, altn: :op, &block)
|
47
|
+
add definition
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class ArrayGroupingDefinition < Parameter::HashParameterDefinition
|
52
|
+
def initialize(*args, **opts)
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
late_init :prototype, getter: false, obligatory: false do |prototype|
|
57
|
+
array = Builder.define_array(:array, altn: :a) do
|
58
|
+
prototype(prototype)
|
59
|
+
default []
|
60
|
+
end
|
61
|
+
add_child array
|
62
|
+
Extensions::Undefined
|
63
|
+
end
|
64
|
+
|
65
|
+
parameter_class ArrayGrouping
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require_relative 'predicate'
|
2
|
+
require_relative '../parameter/parameter'
|
3
|
+
require_relative '../parameter/definition'
|
4
|
+
|
5
|
+
module ParamsReady
|
6
|
+
module Query
|
7
|
+
class CustomPredicate < Parameter::AbstractParameter
|
8
|
+
include Predicate::DelegatingPredicate
|
9
|
+
include Predicate::HavingChildren
|
10
|
+
|
11
|
+
def initialize(definition)
|
12
|
+
super definition
|
13
|
+
@data = definition.type.create
|
14
|
+
end
|
15
|
+
|
16
|
+
def eligible_for_query?(arel_table, context)
|
17
|
+
return false unless context.permitted? self
|
18
|
+
eligibility_test = definition.eligibility_test
|
19
|
+
return true if eligibility_test.nil?
|
20
|
+
|
21
|
+
instance_exec(arel_table, context, &eligibility_test)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_query(arel_table, context: Restriction.blanket_permission)
|
25
|
+
return unless eligible_for_query?(arel_table, context)
|
26
|
+
|
27
|
+
to_query = definition.to_query
|
28
|
+
raise ParamsReadyError, "Method 'to_query' unimplemented in '#{name}'" if to_query.nil?
|
29
|
+
result = instance_exec(arel_table, context, &to_query)
|
30
|
+
|
31
|
+
case result
|
32
|
+
when Arel::Nodes::Node, nil
|
33
|
+
result
|
34
|
+
else
|
35
|
+
literal = Arel::Nodes::SqlLiteral.new(result)
|
36
|
+
grouping = Arel::Nodes::Grouping.new(literal)
|
37
|
+
grouping
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test(record)
|
42
|
+
test = definition.test
|
43
|
+
raise ParamsReadyError, "Method 'test' unimplemented in '#{name}'" if test.nil?
|
44
|
+
self.instance_exec(record, &test)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class CustomPredicateBuilder < Builder
|
49
|
+
PredicateRegistry.register_predicate :custom_predicate, self
|
50
|
+
include AbstractPredicateBuilder::HavingType
|
51
|
+
|
52
|
+
def initialize(name, altn: nil)
|
53
|
+
super CustomPredicateDefinition.new(name, altn: altn)
|
54
|
+
end
|
55
|
+
|
56
|
+
def type_builder_instance(type_name, name, *args, altn:, **opts, &block)
|
57
|
+
builder_class = Builder.builder(type_name)
|
58
|
+
builder_class.instance(name, *args, altn: altn, **opts)
|
59
|
+
end
|
60
|
+
|
61
|
+
def data_object_handles
|
62
|
+
[@definition.name, @definition.altn]
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_query(&proc)
|
66
|
+
@definition.set_to_query(proc)
|
67
|
+
end
|
68
|
+
|
69
|
+
def eligible(&proc)
|
70
|
+
@definition.set_eligibility_test(proc)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test(&proc)
|
74
|
+
@definition.set_test(proc)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class CustomPredicateDefinition < Parameter::AbstractDefinition
|
79
|
+
late_init :type, obligatory: true, freeze: false
|
80
|
+
freeze_variable :type
|
81
|
+
late_init :to_query, obligatory: false
|
82
|
+
late_init :eligibility_test, obligatory: false
|
83
|
+
late_init :test, obligatory: false
|
84
|
+
|
85
|
+
include Parameter::DelegatingDefinition[:type]
|
86
|
+
|
87
|
+
def initialize(*args, type: nil, to_query: nil, test: nil, **opts)
|
88
|
+
@type = type
|
89
|
+
@to_query = to_query
|
90
|
+
@test = test
|
91
|
+
super *args, **opts
|
92
|
+
end
|
93
|
+
|
94
|
+
def finish
|
95
|
+
@type.finish
|
96
|
+
super
|
97
|
+
end
|
98
|
+
|
99
|
+
parameter_class CustomPredicate
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require_relative 'predicate'
|
2
|
+
require_relative 'structured_grouping'
|
3
|
+
require_relative 'join_clause'
|
4
|
+
|
5
|
+
module ParamsReady
|
6
|
+
module Query
|
7
|
+
class ExistsPredicate < StructuredGrouping
|
8
|
+
include Predicate::HavingAssociations
|
9
|
+
|
10
|
+
def to_query(query_table, context: Restriction.blanket_permission)
|
11
|
+
query_table = definition.outer_table || query_table
|
12
|
+
|
13
|
+
subquery_table = self.definition.arel_table
|
14
|
+
raise ParamsReadyError, "Arel table for '#{name}' not set" if subquery_table.nil?
|
15
|
+
|
16
|
+
predicates = predicate_group(subquery_table, context: context)
|
17
|
+
|
18
|
+
join_clause = self.related query_table, subquery_table, context
|
19
|
+
subquery = GroupingOperator.instance(:and).connect(predicates, join_clause)
|
20
|
+
select = subquery_table.where(subquery)
|
21
|
+
query = select.take(1).project(Arel.star).exists
|
22
|
+
if definition.has_child?(:existence) && self[:existence].unwrap == :none
|
23
|
+
query.not
|
24
|
+
else
|
25
|
+
query
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def related(query_table, subquery_table, context)
|
30
|
+
return nil if definition.related.nil?
|
31
|
+
|
32
|
+
grouping = definition.related.to_arel(query_table, subquery_table, context, self)
|
33
|
+
subquery_table.grouping(grouping)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test(record)
|
37
|
+
return nil unless is_definite?
|
38
|
+
|
39
|
+
collection = dig(record, definition.path_to_collection)
|
40
|
+
|
41
|
+
result = if collection.nil?
|
42
|
+
false
|
43
|
+
else
|
44
|
+
collection.any? do |item|
|
45
|
+
super item
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
if definition.has_child?(:existence) && self[:existence].unwrap == :none
|
50
|
+
!result
|
51
|
+
else
|
52
|
+
result
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class ExistsPredicateBuilder < Builder
|
58
|
+
PredicateRegistry.register_predicate :exists_predicate, self
|
59
|
+
|
60
|
+
include GroupingLike
|
61
|
+
include Parameter::AbstractHashParameterBuilder::HashLike
|
62
|
+
include HavingArelTable
|
63
|
+
|
64
|
+
def self.instance(name, altn: nil, coll: nil)
|
65
|
+
new ExistsPredicateDefinition.new(name, altn: altn, path_to_collection: Array(coll))
|
66
|
+
end
|
67
|
+
|
68
|
+
def related(on: nil, eq: nil, &block)
|
69
|
+
join_statement = JoinStatement.new(on: on, eq: eq, &block)
|
70
|
+
@definition.set_related(join_statement)
|
71
|
+
end
|
72
|
+
|
73
|
+
def outer_table(arel_table)
|
74
|
+
@definition.set_outer_table arel_table
|
75
|
+
end
|
76
|
+
|
77
|
+
def existence(&block)
|
78
|
+
definition = Builder.define_symbol(:existence, altn: :ex) do
|
79
|
+
constrain :enum, [:some, :none]
|
80
|
+
include &block
|
81
|
+
end
|
82
|
+
add definition
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class ExistsPredicateDefinition < StructuredGroupingDefinition
|
87
|
+
late_init :outer_table, obligatory: false, freeze: false
|
88
|
+
late_init :arel_table, obligatory: false, freeze: false
|
89
|
+
late_init :related, obligatory: false, freeze: true
|
90
|
+
|
91
|
+
def initialize(*args, path_to_collection: nil, **opts)
|
92
|
+
@path_to_collection = path_to_collection
|
93
|
+
super *args, **opts
|
94
|
+
end
|
95
|
+
|
96
|
+
def path_to_collection
|
97
|
+
@path_to_collection || [@name]
|
98
|
+
end
|
99
|
+
|
100
|
+
parameter_class ExistsPredicate
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|