params_ready_rails5 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/lib/arel/cte_name.rb +20 -0
  3. data/lib/params_ready/builder.rb +161 -0
  4. data/lib/params_ready/error.rb +31 -0
  5. data/lib/params_ready/extensions/class_reader_writer.rb +33 -0
  6. data/lib/params_ready/extensions/collection.rb +43 -0
  7. data/lib/params_ready/extensions/delegation.rb +25 -0
  8. data/lib/params_ready/extensions/finalizer.rb +26 -0
  9. data/lib/params_ready/extensions/freezer.rb +49 -0
  10. data/lib/params_ready/extensions/hash.rb +46 -0
  11. data/lib/params_ready/extensions/late_init.rb +38 -0
  12. data/lib/params_ready/extensions/registry.rb +44 -0
  13. data/lib/params_ready/extensions/undefined.rb +23 -0
  14. data/lib/params_ready/format.rb +132 -0
  15. data/lib/params_ready/helpers/arel_builder.rb +68 -0
  16. data/lib/params_ready/helpers/callable.rb +14 -0
  17. data/lib/params_ready/helpers/conditional_block.rb +31 -0
  18. data/lib/params_ready/helpers/find_in_hash.rb +22 -0
  19. data/lib/params_ready/helpers/interface_definer.rb +48 -0
  20. data/lib/params_ready/helpers/key_map.rb +176 -0
  21. data/lib/params_ready/helpers/memo.rb +41 -0
  22. data/lib/params_ready/helpers/options.rb +107 -0
  23. data/lib/params_ready/helpers/parameter_definer_class_methods.rb +39 -0
  24. data/lib/params_ready/helpers/parameter_storage_class_methods.rb +63 -0
  25. data/lib/params_ready/helpers/parameter_user_class_methods.rb +35 -0
  26. data/lib/params_ready/helpers/relation_builder_wrapper.rb +35 -0
  27. data/lib/params_ready/helpers/rule.rb +76 -0
  28. data/lib/params_ready/helpers/storage.rb +30 -0
  29. data/lib/params_ready/helpers/usage_rule.rb +36 -0
  30. data/lib/params_ready/input_context.rb +31 -0
  31. data/lib/params_ready/intent.rb +70 -0
  32. data/lib/params_ready/marshaller/array_marshallers.rb +132 -0
  33. data/lib/params_ready/marshaller/builder_module.rb +9 -0
  34. data/lib/params_ready/marshaller/collection.rb +165 -0
  35. data/lib/params_ready/marshaller/definition_module.rb +63 -0
  36. data/lib/params_ready/marshaller/enum_set_marshallers.rb +96 -0
  37. data/lib/params_ready/marshaller/parameter_module.rb +11 -0
  38. data/lib/params_ready/marshaller/polymorph_marshallers.rb +67 -0
  39. data/lib/params_ready/marshaller/struct_marshallers.rb +100 -0
  40. data/lib/params_ready/marshaller/tuple_marshallers.rb +103 -0
  41. data/lib/params_ready/ordering/column.rb +60 -0
  42. data/lib/params_ready/ordering/ordering.rb +276 -0
  43. data/lib/params_ready/output_parameters.rb +138 -0
  44. data/lib/params_ready/pagination/abstract_pagination.rb +18 -0
  45. data/lib/params_ready/pagination/cursor.rb +171 -0
  46. data/lib/params_ready/pagination/direction.rb +148 -0
  47. data/lib/params_ready/pagination/keyset_pagination.rb +254 -0
  48. data/lib/params_ready/pagination/keysets.rb +70 -0
  49. data/lib/params_ready/pagination/nulls.rb +31 -0
  50. data/lib/params_ready/pagination/offset_pagination.rb +130 -0
  51. data/lib/params_ready/pagination/tendency.rb +28 -0
  52. data/lib/params_ready/parameter/abstract_struct_parameter.rb +204 -0
  53. data/lib/params_ready/parameter/array_parameter.rb +197 -0
  54. data/lib/params_ready/parameter/definition.rb +272 -0
  55. data/lib/params_ready/parameter/enum_set_parameter.rb +102 -0
  56. data/lib/params_ready/parameter/parameter.rb +475 -0
  57. data/lib/params_ready/parameter/polymorph_parameter.rb +172 -0
  58. data/lib/params_ready/parameter/state.rb +132 -0
  59. data/lib/params_ready/parameter/struct_parameter.rb +64 -0
  60. data/lib/params_ready/parameter/tuple_parameter.rb +152 -0
  61. data/lib/params_ready/parameter/value_parameter.rb +186 -0
  62. data/lib/params_ready/parameter_definer.rb +14 -0
  63. data/lib/params_ready/parameter_user.rb +35 -0
  64. data/lib/params_ready/query/array_grouping.rb +68 -0
  65. data/lib/params_ready/query/custom_predicate.rb +102 -0
  66. data/lib/params_ready/query/exists_predicate.rb +103 -0
  67. data/lib/params_ready/query/fixed_operator_predicate.rb +77 -0
  68. data/lib/params_ready/query/grouping.rb +177 -0
  69. data/lib/params_ready/query/join_clause.rb +87 -0
  70. data/lib/params_ready/query/nullness_predicate.rb +71 -0
  71. data/lib/params_ready/query/polymorph_predicate.rb +77 -0
  72. data/lib/params_ready/query/predicate.rb +203 -0
  73. data/lib/params_ready/query/predicate_operator.rb +132 -0
  74. data/lib/params_ready/query/relation.rb +337 -0
  75. data/lib/params_ready/query/structured_grouping.rb +58 -0
  76. data/lib/params_ready/query/variable_operator_predicate.rb +125 -0
  77. data/lib/params_ready/query_context.rb +21 -0
  78. data/lib/params_ready/restriction.rb +252 -0
  79. data/lib/params_ready/result.rb +109 -0
  80. data/lib/params_ready/value/coder.rb +210 -0
  81. data/lib/params_ready/value/constraint.rb +198 -0
  82. data/lib/params_ready/value/custom.rb +56 -0
  83. data/lib/params_ready/value/validator.rb +81 -0
  84. data/lib/params_ready/version.rb +7 -0
  85. data/lib/params_ready.rb +28 -0
  86. metadata +227 -0
@@ -0,0 +1,71 @@
1
+ require_relative 'predicate'
2
+ require_relative '../parameter/value_parameter'
3
+
4
+ module ParamsReady
5
+ module Query
6
+ class NullnessPredicate < Parameter::AbstractParameter
7
+ include Predicate::DelegatingPredicate
8
+ include Predicate::HavingAttribute
9
+
10
+ def initialize(definition)
11
+ super definition
12
+ @data = definition.value_parameter.create
13
+ end
14
+
15
+ def build_query(select_expression, context: nil)
16
+ query = select_expression.eq(nil)
17
+ if !unwrap
18
+ query.not
19
+ else
20
+ query
21
+ end
22
+ end
23
+
24
+ def perform_test(record, attribute_name)
25
+ if unwrap
26
+ return true if record.nil?
27
+ record.send(attribute_name).nil?
28
+ else
29
+ return false if record.nil?
30
+ !record.send(attribute_name).nil?
31
+ end
32
+ end
33
+
34
+ def inspect_content
35
+ "#{definition.attribute_name} is_null? #{@data.inspect}"
36
+ end
37
+ end
38
+
39
+ class NullnessPredicateBuilder < AbstractPredicateBuilder
40
+ include HavingAttribute
41
+ PredicateRegistry.register_predicate :nullness_predicate, self
42
+
43
+ include HavingValue
44
+
45
+ def self.instance(name, altn: nil, attr: nil)
46
+ new NullnessPredicateDefinition.new name, altn: altn, attribute_name: attr
47
+ end
48
+ end
49
+
50
+ class NullnessPredicateDefinition < AbstractPredicateDefinition
51
+ include HavingAttribute
52
+ include Parameter::DelegatingDefinition[:value_parameter]
53
+
54
+ attr_reader :value_parameter
55
+ freeze_variables :value_parameter
56
+
57
+ def initialize(*args, attribute_name: nil, **opts)
58
+ super *args, **opts
59
+ @attribute_name = attribute_name
60
+ @value_parameter = Builder.builder(:boolean).instance(self.name, altn: self.altn).fetch
61
+ end
62
+
63
+ def finish
64
+ @value_parameter.finish
65
+ super
66
+ end
67
+
68
+ parameter_class NullnessPredicate
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,77 @@
1
+ require 'forwardable'
2
+ require_relative 'predicate'
3
+ require_relative '../parameter/polymorph_parameter'
4
+
5
+ module ParamsReady
6
+ module Query
7
+ class PolymorphPredicate < Parameter::AbstractParameter
8
+ include Predicate::DelegatingPredicate
9
+ include Predicate::HavingChildren
10
+
11
+ def_delegators :@data,
12
+ :intent_for_children,
13
+ :permission_depends_on
14
+
15
+ def initialize(definition, **_)
16
+ super definition
17
+ @data = definition.polymorph_parameter.create
18
+ end
19
+
20
+ def to_query(arel_table, context: Restriction.blanket_permission)
21
+ data[data.type].to_query_if_eligible(arel_table, context: context)
22
+ end
23
+
24
+ def test(record)
25
+ return nil unless is_definite?
26
+
27
+ data[data.type].test(record)
28
+ end
29
+ end
30
+
31
+ class PolymorphPredicateBuilder < AbstractPredicateBuilder
32
+ PredicateRegistry.register_predicate :polymorph_predicate, self
33
+ include HavingValue
34
+
35
+ def self.instance(name, altn: nil)
36
+ new PolymorphPredicateDefinition.new name, altn: altn
37
+ end
38
+
39
+ def type(type_name, *args, **opts, &block)
40
+ builder = PredicateRegistry.predicate(type_name).instance(*args, **opts)
41
+ builder.instance_eval(&block) unless block.nil?
42
+ type = builder.build
43
+ @definition.add_type type
44
+ end
45
+
46
+ def identifier(identifier)
47
+ @definition.set_identifier(identifier)
48
+ end
49
+ end
50
+
51
+ class PolymorphPredicateDefinition < AbstractPredicateDefinition
52
+ extend Forwardable
53
+
54
+ attr_reader :polymorph_parameter, :name, :altn
55
+ freeze_variable :polymorph_parameter
56
+ def_delegators :@polymorph_parameter,
57
+ :add_type,
58
+ :set_optional,
59
+ :set_default,
60
+ :set_identifier,
61
+ :set_marshaller
62
+
63
+ def initialize(*args, **opts)
64
+ super
65
+ @polymorph_parameter = Parameter::PolymorphParameterDefinition.new(name, altn: altn)
66
+ @optional = false
67
+ end
68
+
69
+ def finish
70
+ @polymorph_parameter.finish
71
+ super
72
+ end
73
+
74
+ parameter_class PolymorphPredicate
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,203 @@
1
+ require_relative '../extensions/registry'
2
+ require_relative '../parameter/array_parameter'
3
+ require_relative '../parameter/enum_set_parameter'
4
+ require_relative '../helpers/arel_builder'
5
+
6
+ module ParamsReady
7
+ module Query
8
+ class AbstractPredicateBuilder < AbstractBuilder
9
+ module HavingType
10
+ def type(type_name, *args, **opts, &block)
11
+ name, altn = data_object_handles
12
+ builder = type_builder_instance(type_name, name, *args, altn: altn, **opts)
13
+ builder.instance_eval(&block) unless block.nil?
14
+ @definition.set_type builder.fetch
15
+ end
16
+
17
+ def type_builder_instance(type_name, name, *args, altn:, **opts)
18
+ AbstractPredicateBuilder.type(type_name)
19
+ .instance(name, *args, altn: altn, **opts)
20
+ end
21
+ end
22
+
23
+ module HavingAttribute
24
+ def associations(*arr)
25
+ arr.each do |name|
26
+ @definition.add_association name
27
+ end
28
+ end
29
+
30
+ def attribute(name: nil, expression: nil, &block)
31
+ expression = if expression
32
+ raise ParamsReadyError, 'Block unexpected' unless block.nil?
33
+ expression
34
+ else
35
+ raise ParamsReadyError, 'Expression unexpected' unless expression.nil?
36
+ block
37
+ end
38
+ @definition.set_attribute(name, expression)
39
+ end
40
+ end
41
+
42
+ include HavingArelTable
43
+
44
+ extend Extensions::Registry
45
+ registry :types, as: :type, getter: true
46
+ register_type :value, Parameter::ValueParameterBuilder
47
+ register_type :array, Parameter::ArrayParameterBuilder
48
+ register_type :enum_set, Parameter::EnumSetParameterBuilder
49
+ end
50
+
51
+ class AbstractPredicateDefinition < Parameter::AbstractDefinition
52
+ late_init :arel_table, obligatory: false, freeze: false
53
+
54
+ module HavingAttribute
55
+ def self.included(base)
56
+ base.collection :associations, :association
57
+ end
58
+
59
+ def set_attribute(name, select_expression)
60
+ @attribute_name = name
61
+ @select_expression = select_expression
62
+ end
63
+
64
+ def attribute_name
65
+ @attribute_name || @name
66
+ end
67
+
68
+ def select_expression
69
+ @select_expression || attribute_name
70
+ end
71
+
72
+ def build_select_expression(arel_table, context)
73
+ arel_builder = Helpers::ArelBuilder.instance(select_expression, arel_table: @arel_table)
74
+ arel = arel_builder.to_arel(arel_table, context, self)
75
+
76
+ arel
77
+ end
78
+
79
+ def alias_select_expression(arel_table, context)
80
+ build_select_expression(arel_table, context).as(attribute_name.to_s)
81
+ end
82
+ end
83
+ end
84
+
85
+ module Predicate
86
+ module HavingChildren
87
+ def context_for_predicates(context)
88
+ intent_for_children(context)
89
+ end
90
+ end
91
+
92
+ module HavingAssociations
93
+ def dig(record, associations)
94
+ associations.reduce(record) do |record, assoc|
95
+ next record if record.nil?
96
+
97
+ record.send assoc
98
+ end
99
+ end
100
+ end
101
+
102
+ module HavingAttribute
103
+ extend Forwardable
104
+ def_delegators :definition, :build_select_expression, :alias_select_expression
105
+ include HavingAssociations
106
+
107
+ def to_query(arel_table, context: Restriction.blanket_permission)
108
+ table = definition.arel_table || arel_table
109
+ select_expression = build_select_expression(table, context)
110
+ build_query(select_expression, context: context)
111
+ end
112
+
113
+ def context_for_predicates(context)
114
+ # We consider a an attribute having parameter atomic
115
+ # so it's permitted per se including its contents
116
+ context.permit_all
117
+ end
118
+
119
+ def test(record)
120
+ return nil unless is_definite?
121
+
122
+ attribute_name = definition.attribute_name
123
+ record = dig(record, definition.associations)
124
+
125
+ perform_test(record, attribute_name)
126
+ end
127
+ end
128
+
129
+ module DelegatingPredicate
130
+ def self.included(base)
131
+ base.include Parameter::DelegatingParameter
132
+ end
133
+
134
+ def eligible_for_query?(_table, context)
135
+ return false unless context.permitted? self
136
+
137
+ is_definite?
138
+ end
139
+
140
+ def to_query_if_eligible(arel_table, context:)
141
+ return unless eligible_for_query?(arel_table, context)
142
+
143
+ context = context_for_predicates(context)
144
+ to_query(arel_table, context: context)
145
+ end
146
+ attr_reader :data
147
+
148
+ end
149
+ end
150
+
151
+ class PredicateRegistry
152
+ extend Extensions::Registry
153
+
154
+ registry :operator_names, as: :operator_by_name, name_method: :name
155
+ registry :operator_alt_names, as: :operator_by_alt_name, name_method: :altn
156
+ registry :predicates, as: :predicate, getter: true
157
+
158
+ def self.operator_by(identifier, format)
159
+ if format.alternative?
160
+ @@operator_alt_names[identifier]
161
+ else
162
+ @@operator_names[identifier]
163
+ end
164
+ end
165
+
166
+ def self.operator(identifier, format, collision_check = false)
167
+ operator = find_operator(identifier, format, collision_check)
168
+ if operator.nil? && !collision_check
169
+ raise("No such operator: #{identifier}")
170
+ end
171
+
172
+ operator
173
+ end
174
+
175
+ def self.find_operator(identifier, format, collision_check)
176
+ operator = operator_by(identifier, format)
177
+ if operator.nil?
178
+ name_as_string = identifier.to_s
179
+ invertor = if format.alternative?
180
+ 'n_'
181
+ else
182
+ 'not_'
183
+ end
184
+ if !collision_check && name_as_string.start_with?(invertor)
185
+ bare_name = name_as_string[invertor.length..-1].to_sym
186
+ inverted = PredicateRegistry.operator(bare_name, format)
187
+ if inverted.nil?
188
+ nil
189
+ elsif inverted.inverse_of.nil?
190
+ Not.new(inverted)
191
+ else
192
+ operator(inverted.inverse_of, format)
193
+ end
194
+ else
195
+ nil
196
+ end
197
+ else
198
+ operator
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,132 @@
1
+ require_relative 'predicate'
2
+
3
+ module ParamsReady
4
+ module Query
5
+ class PredicateOperator
6
+ def self.dup
7
+ self
8
+ end
9
+
10
+ def self.define_operator(name, altn, arel: nil, test: nil, inverse_of: nil)
11
+ define_singleton_method :name do
12
+ name
13
+ end
14
+
15
+ define_singleton_method :altn do
16
+ altn
17
+ end
18
+
19
+ if arel
20
+ define_singleton_method :to_query do |attribute, value|
21
+ attribute.send(arel, value)
22
+ end
23
+ end
24
+
25
+ if test
26
+ define_singleton_method :test do |record, attribute_name, value|
27
+ attribute = record.send attribute_name
28
+ attribute.send test, value
29
+ end
30
+ end
31
+
32
+ define_singleton_method :inverse_of do
33
+ inverse_of
34
+ end
35
+
36
+ unless PredicateRegistry.operator(self.name, Format.instance(:backend), true).nil?
37
+ raise ParamsReadyError, "Operator name taken #{self.name}"
38
+ end
39
+
40
+ unless PredicateRegistry.operator(self.altn, Format.instance(:frontend), true).nil?
41
+ raise ParamsReadyError, "Operator altn taken #{self.name}"
42
+ end
43
+
44
+ PredicateRegistry.register_operator_by_name self
45
+ PredicateRegistry.register_operator_by_alt_name self
46
+ end
47
+
48
+ def altn
49
+ self.class.altn
50
+ end
51
+ end
52
+
53
+ class In < PredicateOperator
54
+ define_operator :in, :in, arel: :in
55
+
56
+ def self.test(record, attribute_name, values)
57
+ attribute = record.send attribute_name
58
+ values.include? attribute
59
+ end
60
+ end
61
+
62
+
63
+ class ComparisonPredicateOperator < PredicateOperator; end
64
+
65
+ class Like < ComparisonPredicateOperator
66
+ define_operator :like, :lk
67
+
68
+ def self.to_query(attribute_name, value)
69
+ attribute_name.matches("%#{value}%")
70
+ end
71
+
72
+ def self.test(record, attribute_name, value)
73
+ attribute = record.send attribute_name
74
+ result = Regexp.new(value, Regexp::IGNORECASE) =~ attribute
75
+ result.nil? ? false : true
76
+ end
77
+ end
78
+
79
+ class Equal < ComparisonPredicateOperator
80
+ define_operator :equal, :eq, arel: :eq, test: :==
81
+ end
82
+
83
+ class NotEqual < ComparisonPredicateOperator
84
+ define_operator :not_equal, :neq, arel: :not_eq, test: :!=
85
+ end
86
+
87
+ class GreaterThan < ComparisonPredicateOperator
88
+ define_operator :greater_than, :gt, arel: :gt, test: :>, inverse_of: :less_than_or_equal
89
+
90
+ def self.test(record, attribute_name, value)
91
+ attribute = record.send attribute_name
92
+ attribute > value
93
+ end
94
+ end
95
+
96
+ class LessThan < ComparisonPredicateOperator
97
+ define_operator :less_than, :lt, arel: :lt, test: :<, inverse_of: :greater_than_or_equal
98
+ end
99
+
100
+ class GraterThanOrEqual < ComparisonPredicateOperator
101
+ define_operator :greater_than_or_equal, :gteq, arel: :gteq, test: :>=, inverse_of: :less_than
102
+ end
103
+
104
+ class LessThanOrEqual < ComparisonPredicateOperator
105
+ define_operator :less_than_or_equal, :lteq, arel: :lteq, test: :<=, inverse_of: :greater_than
106
+ end
107
+
108
+ class Not
109
+ def initialize(operator)
110
+ @operator = operator
111
+ end
112
+
113
+ def name
114
+ "not_#{@operator.name}"
115
+ end
116
+
117
+ def altn
118
+ "n#{@operator.altn}"
119
+ end
120
+
121
+ def test(*args)
122
+ result = @operator.test *args
123
+ !result
124
+ end
125
+
126
+ def to_query(*args)
127
+ result = @operator.to_query(*args)
128
+ result.not
129
+ end
130
+ end
131
+ end
132
+ end