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.
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