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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/lib/arel/cte_name.rb +20 -0
  3. data/lib/params_ready.rb +36 -0
  4. data/lib/params_ready/builder.rb +140 -0
  5. data/lib/params_ready/error.rb +31 -0
  6. data/lib/params_ready/extensions/class_reader_writer.rb +33 -0
  7. data/lib/params_ready/extensions/collection.rb +43 -0
  8. data/lib/params_ready/extensions/delegation.rb +25 -0
  9. data/lib/params_ready/extensions/finalizer.rb +26 -0
  10. data/lib/params_ready/extensions/freezer.rb +49 -0
  11. data/lib/params_ready/extensions/hash.rb +46 -0
  12. data/lib/params_ready/extensions/late_init.rb +38 -0
  13. data/lib/params_ready/extensions/registry.rb +44 -0
  14. data/lib/params_ready/extensions/undefined.rb +15 -0
  15. data/lib/params_ready/format.rb +130 -0
  16. data/lib/params_ready/helpers/arel_builder.rb +68 -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/key_map.rb +176 -0
  20. data/lib/params_ready/helpers/memo.rb +42 -0
  21. data/lib/params_ready/helpers/options.rb +39 -0
  22. data/lib/params_ready/helpers/parameter_definer_class_methods.rb +39 -0
  23. data/lib/params_ready/helpers/parameter_storage_class_methods.rb +36 -0
  24. data/lib/params_ready/helpers/parameter_user_class_methods.rb +31 -0
  25. data/lib/params_ready/helpers/relation_builder_wrapper.rb +35 -0
  26. data/lib/params_ready/helpers/rule.rb +57 -0
  27. data/lib/params_ready/helpers/storage.rb +30 -0
  28. data/lib/params_ready/helpers/usage_rule.rb +18 -0
  29. data/lib/params_ready/input_context.rb +31 -0
  30. data/lib/params_ready/intent.rb +70 -0
  31. data/lib/params_ready/marshaller/array_marshallers.rb +132 -0
  32. data/lib/params_ready/marshaller/builder_module.rb +9 -0
  33. data/lib/params_ready/marshaller/collection.rb +165 -0
  34. data/lib/params_ready/marshaller/definition_module.rb +63 -0
  35. data/lib/params_ready/marshaller/hash_marshallers.rb +100 -0
  36. data/lib/params_ready/marshaller/hash_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/tuple_marshallers.rb +103 -0
  40. data/lib/params_ready/ordering/column.rb +60 -0
  41. data/lib/params_ready/ordering/ordering.rb +276 -0
  42. data/lib/params_ready/output_parameters.rb +127 -0
  43. data/lib/params_ready/pagination/abstract_pagination.rb +18 -0
  44. data/lib/params_ready/pagination/cursor.rb +171 -0
  45. data/lib/params_ready/pagination/direction.rb +148 -0
  46. data/lib/params_ready/pagination/keyset_pagination.rb +254 -0
  47. data/lib/params_ready/pagination/keysets.rb +70 -0
  48. data/lib/params_ready/pagination/nulls.rb +31 -0
  49. data/lib/params_ready/pagination/offset_pagination.rb +130 -0
  50. data/lib/params_ready/pagination/tendency.rb +28 -0
  51. data/lib/params_ready/parameter/abstract_hash_parameter.rb +204 -0
  52. data/lib/params_ready/parameter/array_parameter.rb +197 -0
  53. data/lib/params_ready/parameter/definition.rb +264 -0
  54. data/lib/params_ready/parameter/hash_parameter.rb +63 -0
  55. data/lib/params_ready/parameter/hash_set_parameter.rb +101 -0
  56. data/lib/params_ready/parameter/parameter.rb +456 -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/tuple_parameter.rb +152 -0
  60. data/lib/params_ready/parameter/value_parameter.rb +182 -0
  61. data/lib/params_ready/parameter_definer.rb +14 -0
  62. data/lib/params_ready/parameter_user.rb +43 -0
  63. data/lib/params_ready/query/array_grouping.rb +68 -0
  64. data/lib/params_ready/query/custom_predicate.rb +102 -0
  65. data/lib/params_ready/query/exists_predicate.rb +103 -0
  66. data/lib/params_ready/query/fixed_operator_predicate.rb +77 -0
  67. data/lib/params_ready/query/grouping.rb +177 -0
  68. data/lib/params_ready/query/join_clause.rb +87 -0
  69. data/lib/params_ready/query/nullness_predicate.rb +71 -0
  70. data/lib/params_ready/query/polymorph_predicate.rb +77 -0
  71. data/lib/params_ready/query/predicate.rb +203 -0
  72. data/lib/params_ready/query/predicate_operator.rb +132 -0
  73. data/lib/params_ready/query/relation.rb +337 -0
  74. data/lib/params_ready/query/structured_grouping.rb +58 -0
  75. data/lib/params_ready/query/variable_operator_predicate.rb +125 -0
  76. data/lib/params_ready/query_context.rb +21 -0
  77. data/lib/params_ready/restriction.rb +252 -0
  78. data/lib/params_ready/result.rb +109 -0
  79. data/lib/params_ready/value/coder.rb +181 -0
  80. data/lib/params_ready/value/constraint.rb +198 -0
  81. data/lib/params_ready/value/custom.rb +56 -0
  82. data/lib/params_ready/value/validator.rb +68 -0
  83. metadata +181 -0
@@ -0,0 +1,172 @@
1
+ require_relative 'parameter'
2
+ require_relative 'polymorph_parameter'
3
+ require_relative 'value_parameter'
4
+ require_relative '../marshaller/parameter_module'
5
+ require_relative '../marshaller/definition_module'
6
+ require_relative '../marshaller/builder_module'
7
+ require_relative '../marshaller/polymorph_marshallers'
8
+
9
+ module ParamsReady
10
+ module Parameter
11
+ class PolymorphParameter < Parameter
12
+ include ComplexParameter
13
+ include Marshaller::ParameterModule
14
+
15
+ def_delegators :@definition, :identifier, :types
16
+ intent_for_children :restriction
17
+
18
+ def permission_depends_on
19
+ type = to_type
20
+ return [] if type.nil?
21
+ [type]
22
+ end
23
+
24
+ def set_value_as(value, type, context = Format.instance(:backend), validator = nil)
25
+ parameter = types[type].create
26
+ parameter.set_value value, context, validator
27
+ @value = parameter
28
+ end
29
+
30
+ def type
31
+ return nil unless is_definite?
32
+ bare_value.name
33
+ end
34
+
35
+ def to_type
36
+ bare_value
37
+ end
38
+
39
+ def [](key)
40
+ raise ParamsReadyError, "Type '#{key}' is not set, current type: nil" if is_nil?
41
+
42
+ param = bare_value
43
+ if param.name != key
44
+ raise ParamsReadyError, "Type '#{key}' is not set, current type: '#{param.name}'"
45
+ else
46
+ param
47
+ end
48
+ end
49
+
50
+ protected
51
+
52
+ def child_for_update(path)
53
+ type, *path = path
54
+ [self[type], type, path]
55
+ end
56
+
57
+ def updated_clone(_child_name, updated)
58
+ clone = definition.create
59
+ clone.populate_with(updated, frozen?)
60
+ clone
61
+ end
62
+
63
+ def populate_with(value, freeze = false)
64
+ @value = if freeze && value.frozen?
65
+ value
66
+ else
67
+ value.dup
68
+ end
69
+
70
+ self.freeze if freeze
71
+ self
72
+ end
73
+ end
74
+
75
+ class PolymorphParameterBuilder < Builder
76
+ include Marshaller::BuilderModule
77
+
78
+ register :polymorph
79
+
80
+ def self.instance(name, altn: nil)
81
+ new PolymorphParameterDefinition.new(name, altn: altn)
82
+ end
83
+
84
+ def type(input, *args, **opts, &block)
85
+ definition = self.class.resolve(input, *args, **opts, &block)
86
+ @definition.add_type definition
87
+ end
88
+
89
+ def identifier(identifier)
90
+ @definition.set_identifier identifier
91
+ end
92
+ end
93
+
94
+ class PolymorphParameterDefinition < Definition
95
+ include ValueParameterDefinition::ValueLike
96
+ include Marshaller::DefinitionModule[Marshaller::PolymorphMarshallers.collection]
97
+
98
+ obligatory! :types
99
+ attr_reader :types
100
+ # late_init :identifier, obligatory: true
101
+
102
+ parameter_class PolymorphParameter
103
+ name_for_formatter :polymorph
104
+
105
+ def initialize(*args, identifier: nil, types: [], default_name: nil, **options)
106
+ @types = {}
107
+ @alt_names = {}
108
+ add_types types
109
+ set_default(default_name)
110
+ super *args, **options
111
+ set_identifier identifier unless identifier.nil?
112
+ end
113
+
114
+ def add_type(definition)
115
+ check_type_names(definition)
116
+ raise ParamsReadyError, "Reused name: #{definition.name}" if @types.key? definition.name
117
+ raise ParamsReadyError, "Reused alternative: #{definition.altn}" if @alt_names.key? definition.altn
118
+ @types[definition.name] = definition
119
+ @alt_names[definition.altn] = definition
120
+ end
121
+
122
+ def check_type_names(definition)
123
+ return if @marshallers.nil?
124
+ return unless @marshallers.default?
125
+ default = @marshallers.default
126
+ return unless default.respond_to? :reserved?
127
+
128
+ raise ParamsReadyError, "Reserved name: #{definition.name}" if default.reserved?(definition.name)
129
+ raise ParamsReadyError, "Reserved alternative: #{definition.altn}" if default.reserved?(definition.altn)
130
+ end
131
+
132
+ def add_types(types)
133
+ return if types.nil?
134
+ types.each do |definition|
135
+ add_type definition
136
+ end
137
+ end
138
+
139
+ def set_identifier(type_identifier)
140
+ raise ParamsReadyError, "Identifier already taken: #{type_identifier}" if @alt_names&.key?(type_identifier)
141
+ raise ParamsReadyError, "Identifier already taken: #{type_identifier}" if @types&.key?(type_identifier)
142
+ set_marshaller using: :hash, type_identifier: type_identifier
143
+ end
144
+
145
+ def type(name, context)
146
+ name = if context.alternative?
147
+ @alt_names[name.to_sym].name
148
+ else
149
+ name
150
+ end
151
+ @types[name.to_sym]
152
+ end
153
+
154
+ def set_default(default_name)
155
+ return if default_name.nil?
156
+
157
+ type_def = types[default_name]
158
+ raise ParamsReadyError, "Unknown type '#{default_name}'" if type_def.nil?
159
+ raise ParamsReadyError, "Default type must have default" unless type_def.default_defined?
160
+ frozen = freeze_value(type_def.create)
161
+ @default = frozen
162
+ end
163
+
164
+ def finish
165
+ set_identifier :ppt unless marshallers.default?
166
+ super
167
+ end
168
+
169
+ freeze_variables :types
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,132 @@
1
+ require_relative '../error'
2
+ require_relative '../../params_ready/parameter/hash_parameter'
3
+ require_relative '../query/relation'
4
+
5
+ module ParamsReady
6
+ module Parameter
7
+ class State < HashParameter
8
+ extend Query::Relation::PageAccessors
9
+ extend Forwardable
10
+ def_delegators :definition, :relations
11
+
12
+ def relation(name)
13
+ raise ParamsReadyError, "Relation not defined: '#{name}'" unless relations.include? name
14
+ child(name)
15
+ end
16
+
17
+ def self.relation_delegator(name)
18
+ define_method name do |relation_name, *args|
19
+ relation(relation_name).send(name, *args)
20
+ end
21
+ ruby2_keywords name
22
+ end
23
+
24
+ relation_delegator :ordering
25
+ relation_delegator :num_pages
26
+ relation_delegator :page_no
27
+ relation_delegator :offset
28
+ relation_delegator :limit
29
+ relation_delegator :has_previous?
30
+ relation_delegator :has_previous?
31
+ relation_delegator :has_next?
32
+ relation_delegator :has_page?
33
+
34
+ def page(relation_name = nil, delta = 0, count: nil)
35
+ if delta == 0
36
+ clone
37
+ else
38
+ raise ParamsReadyError, "Relation must be specified when delta is not 0" if relation_name.nil?
39
+
40
+ return nil unless relation(relation_name).pagination.can_yield_page? delta, count: count
41
+ new_offset = relation(relation_name).new_offset(delta)
42
+ update_in(new_offset, [relation_name, :pagination, 0])
43
+ end
44
+ end
45
+
46
+ def current_page
47
+ page
48
+ end
49
+
50
+ def first_page(relation_name)
51
+ value = relation(relation_name).pagination.first_page_value
52
+ update_in(value, [relation_name, :pagination])
53
+ end
54
+
55
+ def last_page(relation_name, *args, **opts)
56
+ value = relation(relation_name).pagination.last_page_value(*args, **opts)
57
+ return if value.nil?
58
+ update_in(value, [relation_name, :pagination])
59
+ end
60
+
61
+ def previous_page(relation_name, delta = 1)
62
+ value = relation(relation_name).pagination.previous_page_value(delta)
63
+ return if value.nil?
64
+ update_in(value, [relation_name, :pagination])
65
+ end
66
+
67
+ def next_page(relation_name, delta = 1, count: nil)
68
+ value = relation(relation_name).pagination.next_page_value(delta, count: count)
69
+ return if value.nil?
70
+ update_in(value, [relation_name, :pagination])
71
+ end
72
+
73
+ def before_page(relation_name, keyset)
74
+ value = relation(relation_name).pagination.before_page_value(keyset)
75
+ update_in(value, [relation_name, :pagination])
76
+ end
77
+
78
+ def after_page(relation_name, keyset)
79
+ value = relation(relation_name).pagination.after_page_value(keyset)
80
+ update_in(value, [relation_name, :pagination])
81
+ end
82
+
83
+ def limited_at(relation_name, limit)
84
+ limit_key = relation(relation_name).pagination.limit_key
85
+ update_in(limit, [relation_name, :pagination, limit_key])
86
+ end
87
+
88
+ def toggled_order(relation_name, column)
89
+ new_order = relation(relation_name).ordering.toggled_order_value(column)
90
+ toggled = update_in(new_order, [relation_name, :ordering])
91
+ toggled.first_page(relation_name)
92
+ end
93
+
94
+ def reordered(relation_name, column, direction)
95
+ new_order = relation(relation_name).ordering.reordered_value(column, direction)
96
+ reordered = update_in(new_order, [relation_name, :ordering])
97
+ reordered.first_page(relation_name)
98
+ end
99
+ end
100
+
101
+ class StateBuilder < HashParameterBuilder
102
+ def relation(relation)
103
+ @definition.add_relation relation
104
+ end
105
+
106
+ def self.instance
107
+ definition = StateDefinition.new(:'', altn: :'')
108
+ new definition
109
+ end
110
+ end
111
+
112
+ class StateDefinition < HashParameterDefinition
113
+ parameter_class State
114
+ attr_reader :relations
115
+
116
+ def initialize(*args, **opts)
117
+ super *args, **opts
118
+ @relations = Set.new
119
+ end
120
+
121
+ def add_relation(relation)
122
+ if @relations.include? relation.name
123
+ raise ParamsReadyError, "Relation already there '#{relation.name}'"
124
+ end
125
+ @relations << relation.name
126
+ add_child relation
127
+ end
128
+
129
+ freeze_variable :relations
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,152 @@
1
+ require 'set'
2
+ require_relative 'parameter'
3
+ require_relative '../builder'
4
+ require_relative 'definition'
5
+ require_relative 'array_parameter'
6
+ require_relative '../marshaller/tuple_marshallers'
7
+ require_relative '../marshaller/definition_module'
8
+ require_relative '../marshaller/builder_module'
9
+ require_relative '../marshaller/parameter_module'
10
+
11
+ module ParamsReady
12
+ module Parameter
13
+ class TupleParameter < Parameter
14
+ include ArrayParameter::ArrayLike
15
+ include Marshaller::ParameterModule
16
+
17
+ def_delegators :@definition, :names, :fields, :separator, :marshaller
18
+
19
+ freeze_variable :value do |array|
20
+ next if Extensions::Undefined.value_indefinite?(array)
21
+ array.each(&:freeze)
22
+ end
23
+
24
+ def method_missing(name, *args)
25
+ integer = ordinal_to_integer(name)
26
+ if integer.nil?
27
+ super
28
+ else
29
+ self[integer - 1]
30
+ end
31
+ end
32
+
33
+ def respond_to_missing?(name, include_private = false)
34
+ return true unless ordinal_to_integer(name).nil?
35
+ super
36
+ end
37
+
38
+ protected
39
+
40
+ def element(index)
41
+ return nil if is_nil?
42
+
43
+ value = bare_value
44
+ if index < 0 || index >= value.length
45
+ raise ParamsReadyError, "Index out of bounds: #{index}"
46
+ else
47
+ value[index]
48
+ end
49
+ end
50
+
51
+ ORDINALS = %i{
52
+ first second third fourth fifth sixth seventh eighth nineth tenth
53
+ }.each_with_index.map do |ordinal, index|
54
+ [ordinal, index + 1]
55
+ end.to_h.freeze
56
+
57
+ def ordinal_to_integer(name)
58
+ integer = ORDINALS[name]
59
+ return nil if integer.nil?
60
+ return nil if definition.arity < integer
61
+
62
+ integer
63
+ end
64
+
65
+ def init_value
66
+ @value = []
67
+ fields.each do |definition|
68
+ @value << definition.create
69
+ end
70
+ end
71
+ end
72
+
73
+ class TupleParameterBuilder < Builder
74
+ include Marshaller::BuilderModule
75
+ register :tuple
76
+
77
+ def self.instance(name, altn: nil)
78
+ new TupleParameterDefinition.new(name, altn: altn)
79
+ end
80
+
81
+ def field(input, *args, **opts, &block)
82
+ definition = self.class.resolve(input, *args, **opts, &block)
83
+ @definition.add_field definition
84
+ end
85
+ end
86
+
87
+ class TupleParameterDefinition < Definition
88
+ include ArrayParameterDefinition::ArrayLike
89
+ include Marshaller::DefinitionModule[Marshaller::TupleMarshallers.collection]
90
+
91
+ class StringMarshaller
92
+ def initialize(separator:)
93
+ @separator = separator
94
+ end
95
+
96
+ def marshal(fields, _format)
97
+ fields.join(@separator)
98
+ end
99
+ end
100
+
101
+ class HashMarshaller
102
+ def marshal(fields, _format)
103
+ fields.each_with_index.map do |field, index|
104
+ [index.to_s, field]
105
+ end.to_h
106
+ end
107
+ end
108
+
109
+ name_for_formatter :tuple
110
+
111
+ parameter_class TupleParameter
112
+
113
+ def initialize(*args, separator: nil, fields: nil, **options)
114
+ @fields = []
115
+ add_fields fields unless fields.nil?
116
+ super *args, **options
117
+ end
118
+
119
+ def add_fields(fields)
120
+ fields.each do |field|
121
+ add_field(field)
122
+ end
123
+ end
124
+
125
+ collection :fields, :field do |field|
126
+ raise ParamsReadyError, "Can't add field if default is present" if default_defined?
127
+ raise ParamsReadyError, "Not a field definition #{field.class.name}" unless field.is_a? AbstractDefinition
128
+ raise ParamsReadyError, "Field is not a value #{field.class.name}" unless field.is_a? ValueParameterDefinition
129
+ raise ParamsReadyError, "Field can't be optional" if field.optional?
130
+ raise ParamsReadyError, "Field can't have default" if field.default_defined?
131
+ field
132
+ end
133
+
134
+ def arity
135
+ @fields.length
136
+ end
137
+
138
+ def ensure_canonical(array)
139
+ raise ParamsReadyError, "Not an array" unless array.is_a? Array
140
+ context = Format.instance(:backend)
141
+ marshaller = marshallers.instance(Array)
142
+ value, _validator = marshaller.canonicalize(self, array, context, nil, freeze: true)
143
+ value
144
+ end
145
+
146
+ def freeze
147
+ @fields.freeze
148
+ super
149
+ end
150
+ end
151
+ end
152
+ end