params_ready_rails5 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|