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.
- checksums.yaml +7 -0
- data/lib/arel/cte_name.rb +20 -0
- data/lib/params_ready/builder.rb +161 -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 +23 -0
- data/lib/params_ready/format.rb +132 -0
- data/lib/params_ready/helpers/arel_builder.rb +68 -0
- data/lib/params_ready/helpers/callable.rb +14 -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/interface_definer.rb +48 -0
- data/lib/params_ready/helpers/key_map.rb +176 -0
- data/lib/params_ready/helpers/memo.rb +41 -0
- data/lib/params_ready/helpers/options.rb +107 -0
- data/lib/params_ready/helpers/parameter_definer_class_methods.rb +39 -0
- data/lib/params_ready/helpers/parameter_storage_class_methods.rb +63 -0
- data/lib/params_ready/helpers/parameter_user_class_methods.rb +35 -0
- data/lib/params_ready/helpers/relation_builder_wrapper.rb +35 -0
- data/lib/params_ready/helpers/rule.rb +76 -0
- data/lib/params_ready/helpers/storage.rb +30 -0
- data/lib/params_ready/helpers/usage_rule.rb +36 -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/enum_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/struct_marshallers.rb +100 -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 +138 -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_struct_parameter.rb +204 -0
- data/lib/params_ready/parameter/array_parameter.rb +197 -0
- data/lib/params_ready/parameter/definition.rb +272 -0
- data/lib/params_ready/parameter/enum_set_parameter.rb +102 -0
- data/lib/params_ready/parameter/parameter.rb +475 -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/struct_parameter.rb +64 -0
- data/lib/params_ready/parameter/tuple_parameter.rb +152 -0
- data/lib/params_ready/parameter/value_parameter.rb +186 -0
- data/lib/params_ready/parameter_definer.rb +14 -0
- data/lib/params_ready/parameter_user.rb +35 -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 +210 -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 +81 -0
- data/lib/params_ready/version.rb +7 -0
- data/lib/params_ready.rb +28 -0
- metadata +227 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
require_relative '../error'
|
2
|
+
|
3
|
+
module ParamsReady
|
4
|
+
module Helpers
|
5
|
+
class ArelBuilder
|
6
|
+
def self.instance(object, arel_table: nil)
|
7
|
+
case object
|
8
|
+
when Arel::Nodes::Node, Arel::Nodes::SqlLiteral, Arel::Attribute
|
9
|
+
raise ParamsReadyError, "Arel table unexpected" unless arel_table.nil? || arel_table == :none
|
10
|
+
ArelObject.new(object)
|
11
|
+
when Proc
|
12
|
+
raise ParamsReadyError, "Arel table unexpected" unless arel_table.nil? || arel_table == :none
|
13
|
+
Callable.new(object)
|
14
|
+
when String, Symbol
|
15
|
+
Literal.new(object, arel_table)
|
16
|
+
else
|
17
|
+
raise ParamsReadyError, "Unexpected type for arel builder: #{object.class.name}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.safe_name(name)
|
22
|
+
name[0...64]
|
23
|
+
end
|
24
|
+
|
25
|
+
class Callable
|
26
|
+
def initialize(proc)
|
27
|
+
@proc = proc
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_arel(*args)
|
31
|
+
result = @proc.call(*args)
|
32
|
+
case result
|
33
|
+
when String, Symbol
|
34
|
+
Helpers::ArelBuilder.instance(result).to_arel(*args)
|
35
|
+
else
|
36
|
+
result
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Literal
|
42
|
+
def initialize(literal, arel_table)
|
43
|
+
@literal = literal.to_s
|
44
|
+
@arel_table = arel_table
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_arel(default_table, _, _)
|
48
|
+
arel_table = @arel_table || default_table
|
49
|
+
if arel_table == :none
|
50
|
+
Arel::Nodes::SqlLiteral.new(@literal)
|
51
|
+
else
|
52
|
+
arel_table[@literal]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class ArelObject
|
58
|
+
def initialize(node)
|
59
|
+
@node = node
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_arel(_, _, _)
|
63
|
+
@node
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative 'rule'
|
2
|
+
require_relative '../error'
|
3
|
+
|
4
|
+
module ParamsReady
|
5
|
+
module Helpers
|
6
|
+
class Conditional
|
7
|
+
def initialize(rule: nil)
|
8
|
+
@rule = Helpers::Rule(rule)
|
9
|
+
freeze
|
10
|
+
end
|
11
|
+
|
12
|
+
def perform?(general_rule, name)
|
13
|
+
if @rule.nil?
|
14
|
+
general_rule
|
15
|
+
else
|
16
|
+
@rule.include?(name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class ConditionalBlock < Conditional
|
22
|
+
attr_reader :block
|
23
|
+
|
24
|
+
def initialize(rule: nil, &block)
|
25
|
+
raise ParamsReadyError, "Block must not be empty" if block.nil?
|
26
|
+
@block = block
|
27
|
+
super(rule: rule)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative '../extensions/undefined'
|
2
|
+
require_relative 'key_map'
|
3
|
+
|
4
|
+
module ParamsReady
|
5
|
+
module Helpers
|
6
|
+
module FindInHash
|
7
|
+
def self.find_in_hash(hash, name_or_path)
|
8
|
+
return false, Extensions::Undefined if hash.nil?
|
9
|
+
|
10
|
+
found = if name_or_path.is_a? Array
|
11
|
+
*path, name = name_or_path
|
12
|
+
Helpers::KeyMap::Mapping::Path.dig(name, hash, path)
|
13
|
+
else
|
14
|
+
Extensions::Hash.indifferent_access(hash, name_or_path, Extensions::Undefined)
|
15
|
+
end
|
16
|
+
|
17
|
+
return false, Extensions::Undefined if found == Extensions::Undefined
|
18
|
+
return true, found
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ParamsReady
|
2
|
+
module Helpers
|
3
|
+
class InterfaceDefiner
|
4
|
+
def initialize(action_names, user)
|
5
|
+
@action_names = action_names
|
6
|
+
@user = user
|
7
|
+
end
|
8
|
+
|
9
|
+
def parameters(*names)
|
10
|
+
names.each do |name|
|
11
|
+
parameter(name)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def relations(*names)
|
16
|
+
names.each do |name|
|
17
|
+
relation(name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def parameter(name)
|
22
|
+
@user.use_parameter(name, only: @action_names)
|
23
|
+
end
|
24
|
+
|
25
|
+
def relation(name)
|
26
|
+
@user.use_relation(name, only: @action_names)
|
27
|
+
end
|
28
|
+
|
29
|
+
def define(parameter: nil, relation: nil, parameters: [], relations: [], &block)
|
30
|
+
parameters = self.class.complete_list(parameter, parameters)
|
31
|
+
parameters(*parameters)
|
32
|
+
relations = self.class.complete_list(relation, relations)
|
33
|
+
relations(*relations)
|
34
|
+
instance_eval(&block) unless block.nil?
|
35
|
+
@option
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.complete_list(singular, plural)
|
39
|
+
list = singular.nil? ? plural : [singular, *plural]
|
40
|
+
normalize_list(list)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.normalize_list(list)
|
44
|
+
list.map(&:to_sym)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require_relative '../error'
|
2
|
+
require_relative '../extensions/undefined'
|
3
|
+
require_relative '../extensions/hash'
|
4
|
+
|
5
|
+
module ParamsReady
|
6
|
+
module Helpers
|
7
|
+
class KeyMap
|
8
|
+
class Mapping
|
9
|
+
class Path
|
10
|
+
attr_reader :path, :names
|
11
|
+
|
12
|
+
def initialize(path, names = [])
|
13
|
+
@path = path.map(&:to_sym).freeze
|
14
|
+
@names = names
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_names(names)
|
18
|
+
names.each{ |name| add_name(name) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_name(name)
|
22
|
+
@names << name
|
23
|
+
end
|
24
|
+
|
25
|
+
def dig(name, hash)
|
26
|
+
self.class.dig(name, hash, @path)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.dig(name, hash, path)
|
30
|
+
result = path.reduce(hash) do |current, name|
|
31
|
+
next unless Extensions::Hash.acts_as_hash?(current)
|
32
|
+
|
33
|
+
Extensions::Hash.indifferent_access current, name, nil
|
34
|
+
end
|
35
|
+
|
36
|
+
return Extensions::Undefined unless Extensions::Hash.acts_as_hash?(result)
|
37
|
+
|
38
|
+
Extensions::Hash.indifferent_access result, name, Extensions::Undefined
|
39
|
+
end
|
40
|
+
|
41
|
+
def store(name, value, hash)
|
42
|
+
self.class.store(name, value, hash, @path)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.store(name, value, hash, path)
|
46
|
+
return if value == Extensions::Undefined
|
47
|
+
|
48
|
+
result = path.reduce(hash) do |current, name|
|
49
|
+
current[name] ||= {}
|
50
|
+
current[name]
|
51
|
+
end
|
52
|
+
|
53
|
+
result[name] = value
|
54
|
+
result
|
55
|
+
end
|
56
|
+
|
57
|
+
def =~(other)
|
58
|
+
raise ParamsReadyError, "Can't match path with #{other.class.name}" unless other.is_a? Path
|
59
|
+
path == other.path
|
60
|
+
end
|
61
|
+
|
62
|
+
def ==(other)
|
63
|
+
raise ParamsReadyError, "Can't compare path with #{other.class.name}" unless other.is_a? Path
|
64
|
+
path == other.path && names == other.names
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def initialize(alt_path, alt_names, std_path, std_names)
|
69
|
+
if alt_names.length != std_names.length
|
70
|
+
msg = "Expected equal number of alternative and standard names, got #{alt_names.length}/#{std_names.length}"
|
71
|
+
raise ParamsReadyError, msg
|
72
|
+
end
|
73
|
+
|
74
|
+
@alt = Path.new(alt_path, alt_names)
|
75
|
+
@std = Path.new(std_path, std_names)
|
76
|
+
end
|
77
|
+
|
78
|
+
def add_names(altn, stdn)
|
79
|
+
@alt.add_name altn
|
80
|
+
@std.add_name stdn
|
81
|
+
end
|
82
|
+
|
83
|
+
def remap(from, to, input, target)
|
84
|
+
path(from).names.each_with_index do |input_name, idx|
|
85
|
+
value = dig(from, input_name, input)
|
86
|
+
target_name = path(to).names[idx]
|
87
|
+
store(to, target_name, value, target)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def merge!(other)
|
92
|
+
raise ParamsReadyError, "Can't merge non_matching mapping" unless self =~ other
|
93
|
+
|
94
|
+
@alt.add_names(other.alt.names)
|
95
|
+
@std.add_names(other.std.names)
|
96
|
+
end
|
97
|
+
|
98
|
+
def dig(schema, name, hash)
|
99
|
+
path(schema).dig(name, hash)
|
100
|
+
end
|
101
|
+
|
102
|
+
def store(schema, name, value, hash)
|
103
|
+
path(schema).store(name, value, hash)
|
104
|
+
end
|
105
|
+
|
106
|
+
def path(schema)
|
107
|
+
case schema
|
108
|
+
when :alt then @alt
|
109
|
+
when :std then @std
|
110
|
+
else
|
111
|
+
raise ParamsReadyError, "Unexpected naming schema: #{schema}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def =~(other)
|
116
|
+
raise ParamsReadyError, "Can't match path with #{other.class.name}" unless other.is_a? Mapping
|
117
|
+
return false unless path(:alt) =~ other.path(:alt)
|
118
|
+
return false unless path(:std) =~ other.path(:std)
|
119
|
+
|
120
|
+
true
|
121
|
+
end
|
122
|
+
|
123
|
+
protected
|
124
|
+
attr_reader :alt, :std
|
125
|
+
end
|
126
|
+
|
127
|
+
def initialize
|
128
|
+
@mappings = []
|
129
|
+
end
|
130
|
+
|
131
|
+
def map(from, to:)
|
132
|
+
alt_path, alt_names = self.class.split_map(from)
|
133
|
+
std_path, std_names = self.class.split_map(to)
|
134
|
+
mapping = Mapping.new(alt_path, alt_names, std_path, std_names)
|
135
|
+
merge_or_add_mapping(mapping)
|
136
|
+
self
|
137
|
+
end
|
138
|
+
|
139
|
+
def merge_or_add_mapping(mapping)
|
140
|
+
if (existing = @mappings.find { |candidate| candidate =~ mapping })
|
141
|
+
existing.merge!(mapping)
|
142
|
+
else
|
143
|
+
@mappings << mapping
|
144
|
+
end
|
145
|
+
mapping
|
146
|
+
end
|
147
|
+
|
148
|
+
def to_standard(hash)
|
149
|
+
remap(:alt, :std, hash)
|
150
|
+
end
|
151
|
+
|
152
|
+
def to_alternative(hash)
|
153
|
+
remap(:std, :alt, hash)
|
154
|
+
end
|
155
|
+
|
156
|
+
def remap(from, to, input)
|
157
|
+
@mappings.each_with_object({}) do |mapping, result|
|
158
|
+
mapping.remap(from, to, input, result)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def freeze
|
163
|
+
@mappings.each(&:freeze)
|
164
|
+
super
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.split_map(array)
|
168
|
+
raise ParamsReadyError, "Array expected, got: #{array.class.name}" unless array.is_a? Array
|
169
|
+
names = array.last || []
|
170
|
+
raise ParamsReadyError, "Array expected, got: #{names.class.name}" unless names.is_a? Array
|
171
|
+
paths = array[0...-1]
|
172
|
+
[paths, names]
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative '../extensions/undefined'
|
2
|
+
require_relative '../extensions/hash'
|
3
|
+
|
4
|
+
|
5
|
+
|
6
|
+
module ParamsReady
|
7
|
+
module Helpers
|
8
|
+
class Memo
|
9
|
+
def initialize(slots = 1)
|
10
|
+
raise ParamsReadyError, "Expected positive value for number of slots, got: '#{slots}'" unless slots > 0
|
11
|
+
@slots = slots
|
12
|
+
@cache = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def cached_value(key)
|
16
|
+
cache = @cache
|
17
|
+
return Extensions::Undefined if cache.nil?
|
18
|
+
return Extensions::Undefined unless cache.key? key
|
19
|
+
|
20
|
+
cache[key]
|
21
|
+
end
|
22
|
+
|
23
|
+
def cache_value(value, key)
|
24
|
+
stale = @cache
|
25
|
+
return if stale&.key? key
|
26
|
+
|
27
|
+
frozen = Extensions::Hash.try_deep_freeze(value)
|
28
|
+
|
29
|
+
fresh = if stale.nil? || @slots == 1
|
30
|
+
{ key => frozen }
|
31
|
+
else
|
32
|
+
kept = stale.to_a.last(@slots - 1)
|
33
|
+
|
34
|
+
[*kept, [key, frozen]].to_h
|
35
|
+
end
|
36
|
+
|
37
|
+
@cache = fresh.freeze
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require_relative 'storage'
|
2
|
+
require_relative 'usage_rule'
|
3
|
+
|
4
|
+
module ParamsReady
|
5
|
+
module Helpers
|
6
|
+
class Options
|
7
|
+
attr_reader :parameters, :relations
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@parameter_rules = Hash.new
|
11
|
+
@relation_rules = Hash.new
|
12
|
+
@memo = { definitions: {} }
|
13
|
+
end
|
14
|
+
|
15
|
+
def reset_memo!(*args)
|
16
|
+
args.each do |key|
|
17
|
+
@memo[key].clear
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def dup
|
22
|
+
duplicate = Options.new
|
23
|
+
@parameter_rules.each do |_, rule|
|
24
|
+
duplicate.merge_parameter_rule(rule)
|
25
|
+
end
|
26
|
+
@relation_rules.each do |_, rule|
|
27
|
+
duplicate.merge_relation_rule(rule)
|
28
|
+
end
|
29
|
+
duplicate
|
30
|
+
end
|
31
|
+
|
32
|
+
def relation_definitions_for(name)
|
33
|
+
definitions_for(name, relation_rules)
|
34
|
+
end
|
35
|
+
|
36
|
+
def parameter_definitions_for(name)
|
37
|
+
definitions_for(name, parameter_rules)
|
38
|
+
end
|
39
|
+
|
40
|
+
def definitions_for(name, rules)
|
41
|
+
rules.each_with_object([]) do |(_, rule), result|
|
42
|
+
next unless rule.valid_for?(name)
|
43
|
+
|
44
|
+
result << rule.parameter_definition
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def use_parameter(param, rule_args = :all)
|
49
|
+
rule = UsageRule.new(param, rule_args)
|
50
|
+
merge_parameter_rule(rule)
|
51
|
+
end
|
52
|
+
|
53
|
+
def merge_parameter_rule(rule)
|
54
|
+
reset_memo!(:definitions)
|
55
|
+
@parameter_rules = self.class.merge_rule(rule, @parameter_rules)
|
56
|
+
end
|
57
|
+
|
58
|
+
def use_relation(relation, rule_args = :all)
|
59
|
+
rule = UsageRule.new(relation, rule_args)
|
60
|
+
merge_relation_rule(rule)
|
61
|
+
end
|
62
|
+
|
63
|
+
def merge_relation_rule(rule)
|
64
|
+
reset_memo!(:definitions)
|
65
|
+
@relation_rules = self.class.merge_rule(rule, @relation_rules)
|
66
|
+
end
|
67
|
+
|
68
|
+
def parameter_rules
|
69
|
+
if block_given?
|
70
|
+
@parameter_rules.each_value do |rule|
|
71
|
+
yield rule
|
72
|
+
end
|
73
|
+
end
|
74
|
+
@parameter_rules
|
75
|
+
end
|
76
|
+
|
77
|
+
def relation_rules
|
78
|
+
if block_given?
|
79
|
+
@relation_rules.each_value do |rule|
|
80
|
+
yield rule
|
81
|
+
end
|
82
|
+
end
|
83
|
+
@relation_rules
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_state_for(key)
|
87
|
+
@memo[:definitions][key] ||= begin
|
88
|
+
builder = Parameter::StateBuilder.instance
|
89
|
+
parameter_definitions_for(key).each do |definition|
|
90
|
+
builder.add definition
|
91
|
+
end
|
92
|
+
relation_definitions_for(key).each do |definition|
|
93
|
+
builder.relation definition
|
94
|
+
end
|
95
|
+
builder.build
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.merge_rule(rule, rules)
|
100
|
+
existing = rules[rule.name]
|
101
|
+
merged = rule.merge(existing)
|
102
|
+
rules[rule.name] = merged
|
103
|
+
rules
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative 'relation_builder_wrapper'
|
2
|
+
require_relative '../builder'
|
3
|
+
|
4
|
+
module ParamsReady
|
5
|
+
module Helpers
|
6
|
+
module ParameterDefinerClassMethods
|
7
|
+
def define_relation(*args, **opts, &block)
|
8
|
+
wrapper = ParamsReady::Helpers::RelationBuilderWrapper.new self, *args, **opts
|
9
|
+
wrapper.instance_eval(&block) unless block.nil?
|
10
|
+
relation = wrapper.build
|
11
|
+
params_ready_storage.add_relation relation
|
12
|
+
end
|
13
|
+
|
14
|
+
def define_parameter(type, *args, **opts, &block)
|
15
|
+
full_name = "define_#{type}"
|
16
|
+
parameter = Builder.send(full_name, *args, **opts, &block)
|
17
|
+
params_ready_storage.add_parameter parameter
|
18
|
+
end
|
19
|
+
|
20
|
+
def all_relations
|
21
|
+
relations = if superclass.respond_to? :all_relations
|
22
|
+
superclass.all_relations
|
23
|
+
else
|
24
|
+
{}
|
25
|
+
end
|
26
|
+
relations.merge(params_ready_storage.relations)
|
27
|
+
end
|
28
|
+
|
29
|
+
def all_parameters
|
30
|
+
parameters = if superclass.respond_to? :all_parameters
|
31
|
+
superclass.all_parameters
|
32
|
+
else
|
33
|
+
{}
|
34
|
+
end
|
35
|
+
parameters.merge(params_ready_storage.parameters)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require_relative 'storage'
|
2
|
+
require_relative '../error'
|
3
|
+
require_relative 'rule'
|
4
|
+
|
5
|
+
module ParamsReady
|
6
|
+
module Helpers
|
7
|
+
module ParameterStorageClassMethods
|
8
|
+
def params_ready_storage
|
9
|
+
@params_ready_storage ||= Storage.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def relation_definition(key)
|
13
|
+
relations = params_ready_storage.relations
|
14
|
+
sym_key = key.to_sym
|
15
|
+
if relations.key?(sym_key)
|
16
|
+
relations[sym_key]
|
17
|
+
elsif superclass.respond_to? :relation_definition
|
18
|
+
superclass.relation_definition sym_key
|
19
|
+
else
|
20
|
+
raise ParamsReadyError, "Unknown relation '#{sym_key}'"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def parameter_definition(key)
|
25
|
+
parameters = params_ready_storage.parameters
|
26
|
+
sym_key = key.to_sym
|
27
|
+
if parameters.key? sym_key
|
28
|
+
parameters[sym_key]
|
29
|
+
elsif superclass.respond_to? :parameter_definition
|
30
|
+
superclass.parameter_definition sym_key
|
31
|
+
else
|
32
|
+
raise ParamsReadyError, "Unknown parameter '#{sym_key}'"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def include_parameters(parameter_definer, rule = nil)
|
37
|
+
rule = Helpers::Rule(rule)
|
38
|
+
parameter_definer.all_parameters.each do |key, definition|
|
39
|
+
next if rule && !rule.include?(key)
|
40
|
+
|
41
|
+
add_parameter(definition)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_parameter(definition)
|
46
|
+
params_ready_storage.add_parameter(definition)
|
47
|
+
end
|
48
|
+
|
49
|
+
def include_relations(parameter_definer, rule = nil)
|
50
|
+
rule = Helpers::Rule(rule)
|
51
|
+
parameter_definer.all_relations.each do |key, definition|
|
52
|
+
next if rule && !rule.include?(key)
|
53
|
+
|
54
|
+
add_relation(definition)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_relation(definition)
|
59
|
+
params_ready_storage.add_relation(definition)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'interface_definer'
|
2
|
+
|
3
|
+
module ParamsReady
|
4
|
+
module Helpers
|
5
|
+
module ParameterUserClassMethods
|
6
|
+
def params_ready_option
|
7
|
+
@params_ready_option ||= begin
|
8
|
+
if superclass.respond_to? :params_ready_option
|
9
|
+
# This works on assumption that superclass
|
10
|
+
# definition doesn't change during execution
|
11
|
+
superclass.params_ready_option.dup
|
12
|
+
else
|
13
|
+
ParamsReady::Helpers::Options.new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def use_parameter(name, rule = :all)
|
19
|
+
parameter = parameter_definition name
|
20
|
+
params_ready_option.use_parameter parameter, rule
|
21
|
+
end
|
22
|
+
|
23
|
+
def use_relation(name, rule = :all)
|
24
|
+
relation = relation_definition name
|
25
|
+
params_ready_option.use_relation relation, rule
|
26
|
+
end
|
27
|
+
|
28
|
+
def action_interface(*action_names, **opts, &block)
|
29
|
+
definer = InterfaceDefiner.new(action_names, self)
|
30
|
+
|
31
|
+
definer.define(**opts, &block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative '../query/relation'
|
2
|
+
|
3
|
+
module ParamsReady
|
4
|
+
module Helpers
|
5
|
+
class RelationBuilderWrapper
|
6
|
+
def initialize(cache, *args, **opts)
|
7
|
+
@cache = cache
|
8
|
+
@builder = Query::RelationParameterBuilder.instance *args, **opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def capture(*names)
|
12
|
+
names.each do |name|
|
13
|
+
definition = @cache.parameter_definition(name)
|
14
|
+
@builder.add definition
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
ruby2_keywords def method_missing(name, *args, &block)
|
19
|
+
if @builder.respond_to? name
|
20
|
+
@builder.send name, *args, &block
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def respond_to_missing?(name, include_private = false)
|
27
|
+
if @builder.respond_to? name
|
28
|
+
true
|
29
|
+
else
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|