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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 66d9de173024436c9fb9ebe426ac1f7b751ed955575473d83721cf9df4918fe0
|
4
|
+
data.tar.gz: 40bb30ea77ca4d56770ee2bb1bbbb9364d23ec03452c53f1124dc97216f44631
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 985bb72fb65626fa445292ecde4e7a81d548ba7ff48e147df8771b397cf01adc66a9251f10df840edc135ad087bffa92c70df480f22dd31492f66f8a92198d7b
|
7
|
+
data.tar.gz: fa273d9975c6fd5e1de9b81b88b6848df207fc3a1995e5575fd9cba4bfb03ea7741e2f2735451d126b9d41af04c49a5976239621e9c11db50f4df8a6730651e6
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Arel # :nodoc: all
|
2
|
+
module Nodes
|
3
|
+
class CteName < Unary
|
4
|
+
alias :name :expr
|
5
|
+
|
6
|
+
def initialize(expr)
|
7
|
+
expr = SqlLiteral.new(expr)
|
8
|
+
super expr
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Visitors
|
14
|
+
class ToSql < Reduce
|
15
|
+
def visit_Arel_Nodes_CteName(o, collector)
|
16
|
+
collector << o.expr
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require_relative 'extensions/registry'
|
2
|
+
require_relative 'helpers/rule'
|
3
|
+
|
4
|
+
module ParamsReady
|
5
|
+
class AbstractBuilder
|
6
|
+
module HavingArelTable
|
7
|
+
def arel_table(arel_table)
|
8
|
+
@definition.set_arel_table arel_table
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module HavingModel
|
13
|
+
def model(model_class)
|
14
|
+
@definition.set_model_class model_class
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
extend Extensions::Registry
|
19
|
+
registry :builders, as: :builder, getter: true do |name, _|
|
20
|
+
full_name = "define_#{name}"
|
21
|
+
raise ParamsReadyError, "Reserved name: #{full_name}" if method_defined?(full_name)
|
22
|
+
Builder.define_singleton_method(full_name) do |*args, **opts, &block|
|
23
|
+
define_parameter(name, *args, **opts, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.register(name)
|
28
|
+
register_builder(name, self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.register_deprecated(name, use:)
|
32
|
+
raise ParamsReadyError, 'Recommended replacement must not be nil' if use.nil?
|
33
|
+
@deprecated ||= {}
|
34
|
+
@deprecated[name] = use.to_s.freeze
|
35
|
+
register_builder(name, self)
|
36
|
+
end
|
37
|
+
|
38
|
+
class << self
|
39
|
+
alias_method :fetch_builder, :builder
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.builder(name)
|
43
|
+
use = @deprecated[name] if @deprecated&.key? name
|
44
|
+
warn "Builder name deprecated: #{name}, use: #{use}" unless use.nil?
|
45
|
+
fetch_builder(name)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.define_parameter(type, *args, **opts, &block)
|
49
|
+
builder_class = builder(type)
|
50
|
+
builder = builder_class.instance(*args, **opts)
|
51
|
+
builder.include(&block) unless block.nil?
|
52
|
+
builder.build
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.define_registered_parameter(name, *args, **opts, &block)
|
56
|
+
full_name = "define_#{name}"
|
57
|
+
send(full_name, *args, **opts, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.resolve(input, *args, **opts, &block)
|
61
|
+
if input.is_a? Parameter::AbstractDefinition
|
62
|
+
input
|
63
|
+
else
|
64
|
+
define_registered_parameter(input, *args, **opts, &block)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.instance(*args, **opts)
|
69
|
+
new *args, **opts
|
70
|
+
end
|
71
|
+
|
72
|
+
private_class_method :new
|
73
|
+
|
74
|
+
def initialize(definition)
|
75
|
+
@definition = definition
|
76
|
+
end
|
77
|
+
|
78
|
+
def include(&block)
|
79
|
+
instance_eval(&block)
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
83
|
+
def fetch
|
84
|
+
d = @definition
|
85
|
+
@definition = nil
|
86
|
+
d
|
87
|
+
end
|
88
|
+
|
89
|
+
def build
|
90
|
+
@definition.finish
|
91
|
+
@definition
|
92
|
+
end
|
93
|
+
|
94
|
+
def open?
|
95
|
+
return false if @definition.nil?
|
96
|
+
return false if @definition.frozen?
|
97
|
+
|
98
|
+
true
|
99
|
+
end
|
100
|
+
|
101
|
+
module HavingValue
|
102
|
+
def optional
|
103
|
+
@definition.set_optional true
|
104
|
+
end
|
105
|
+
|
106
|
+
def default(val)
|
107
|
+
@definition.set_default(val, **{})
|
108
|
+
end
|
109
|
+
|
110
|
+
def no_output(rule: nil)
|
111
|
+
@definition.set_no_output Helpers::Rule(rule) || true
|
112
|
+
end
|
113
|
+
|
114
|
+
def no_input(*arr, rule: nil)
|
115
|
+
@definition.set_no_input *arr, rule: rule
|
116
|
+
end
|
117
|
+
|
118
|
+
def local(*arr, rule: nil)
|
119
|
+
@definition.set_local *arr, rule: rule
|
120
|
+
end
|
121
|
+
|
122
|
+
def preprocess(rule: nil, &block)
|
123
|
+
@definition.set_preprocessor rule: rule, &block
|
124
|
+
end
|
125
|
+
|
126
|
+
def populate(&block)
|
127
|
+
@definition.set_populator block
|
128
|
+
end
|
129
|
+
|
130
|
+
def postprocess(rule: nil, &block)
|
131
|
+
@definition.set_postprocessor rule: rule, &block
|
132
|
+
end
|
133
|
+
|
134
|
+
def marshal(*args, **opts)
|
135
|
+
@definition.set_marshaller(*args, **opts)
|
136
|
+
end
|
137
|
+
|
138
|
+
def memoize(slots = 1)
|
139
|
+
@definition.set_memoize(slots)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Builder < AbstractBuilder
|
145
|
+
include HavingValue
|
146
|
+
|
147
|
+
def helper(name, &block)
|
148
|
+
@definition.add_helper [name, block]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
module DelegatingBuilder
|
153
|
+
def self.[](delegee_name)
|
154
|
+
mod = Module.new
|
155
|
+
Extensions::Delegation.delegate(mod) do
|
156
|
+
@definition.send(delegee_name)
|
157
|
+
end
|
158
|
+
mod
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ParamsReady
|
2
|
+
class ParamsReadyError < RuntimeError; end
|
3
|
+
|
4
|
+
class ErrorWrapper < ParamsReadyError
|
5
|
+
attr_reader :error
|
6
|
+
|
7
|
+
def initialize(error)
|
8
|
+
@error = error
|
9
|
+
end
|
10
|
+
|
11
|
+
def message
|
12
|
+
@error.message
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class PreprocessorError < ErrorWrapper; end
|
17
|
+
class PostprocessorError < ErrorWrapper; end
|
18
|
+
class PopulatorError < ErrorWrapper; end
|
19
|
+
|
20
|
+
class ValueMissingError < StandardError
|
21
|
+
def initialize(name)
|
22
|
+
super "#{name}: value is nil"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class CoercionError < RuntimeError
|
27
|
+
def initialize(input, class_name)
|
28
|
+
super "can't coerce '#{input}' into #{class_name}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative '../error'
|
2
|
+
|
3
|
+
module ParamsReady
|
4
|
+
module Extensions
|
5
|
+
module ClassReaderWriter
|
6
|
+
def class_reader_writer(method_name)
|
7
|
+
ivar = :"@#{method_name}"
|
8
|
+
define_singleton_method method_name do |*args|
|
9
|
+
if args.length == 0
|
10
|
+
value = instance_variable_get(ivar)
|
11
|
+
if value.nil?
|
12
|
+
if superclass.respond_to? method_name
|
13
|
+
superclass.send method_name
|
14
|
+
else
|
15
|
+
raise ParamsReadyError, "Class variable '#{ivar}' not set for '#{name}'"
|
16
|
+
end
|
17
|
+
else
|
18
|
+
value
|
19
|
+
end
|
20
|
+
elsif args.length == 1
|
21
|
+
if instance_variable_get(ivar).nil?
|
22
|
+
instance_variable_set(ivar, args[0])
|
23
|
+
else
|
24
|
+
raise ParamsReadyError, "Class variable '#{ivar}' already set for '#{name}'"
|
25
|
+
end
|
26
|
+
else
|
27
|
+
raise ParamsReadyError, "Unexpected parameters to '#{method_name}': #{args}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative '../error'
|
2
|
+
|
3
|
+
module ParamsReady
|
4
|
+
module Extensions
|
5
|
+
module Collection
|
6
|
+
def collection(
|
7
|
+
collection_name,
|
8
|
+
element_name,
|
9
|
+
freeze_collection: true,
|
10
|
+
freeze_value: true,
|
11
|
+
getter: true,
|
12
|
+
obligatory: false,
|
13
|
+
&block
|
14
|
+
)
|
15
|
+
full_name = "@#{collection_name}"
|
16
|
+
define_method "add_#{element_name}" do |value|
|
17
|
+
value = instance_exec(value, &block) unless block.nil?
|
18
|
+
next if value == Extensions::Undefined
|
19
|
+
|
20
|
+
collection = send collection_name
|
21
|
+
value.freeze if freeze_value
|
22
|
+
collection << value
|
23
|
+
end
|
24
|
+
|
25
|
+
if getter
|
26
|
+
define_method collection_name do
|
27
|
+
if instance_variable_defined? full_name
|
28
|
+
instance_variable_get full_name
|
29
|
+
elsif frozen?
|
30
|
+
[].freeze
|
31
|
+
else
|
32
|
+
instance_variable_set full_name, []
|
33
|
+
instance_variable_get full_name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
obligatory! collection_name if obligatory
|
39
|
+
freeze_variable collection_name if freeze_collection
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ParamsReady
|
2
|
+
module Extensions
|
3
|
+
module Delegation
|
4
|
+
def self.delegate(mod, &to)
|
5
|
+
mod.define_method :method_missing do |name, *args, &block|
|
6
|
+
delegee = instance_eval(&to)
|
7
|
+
if delegee.respond_to? name
|
8
|
+
delegee.send name, *args, &block
|
9
|
+
else
|
10
|
+
super name, *args, &block
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
mod.define_method :respond_to_missing? do |name, include_private = false|
|
15
|
+
delegee = instance_eval(&to)
|
16
|
+
if delegee.respond_to? name
|
17
|
+
true
|
18
|
+
else
|
19
|
+
super name, include_private
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ParamsReady
|
2
|
+
module Extensions
|
3
|
+
module Finalizer
|
4
|
+
def obligatory!(*args)
|
5
|
+
obligatory.concat args
|
6
|
+
end
|
7
|
+
|
8
|
+
def obligatory
|
9
|
+
@obligatory ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
def finish
|
14
|
+
self.class.obligatory.each do |name|
|
15
|
+
value = instance_variable_get("@#{name}")
|
16
|
+
raise ParamsReadyError, "Obligatory property is nil: #{name}" if value.nil?
|
17
|
+
if value.respond_to? :empty? and value.empty?
|
18
|
+
raise ParamsReadyError, "Obligatory property is empty: #{name}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
self
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module ParamsReady
|
2
|
+
module Extensions
|
3
|
+
module Freezer
|
4
|
+
def variables_to_freeze
|
5
|
+
# This works on assumption classes
|
6
|
+
# are not redefined during runtime
|
7
|
+
@cached_variables_to_freeze ||= begin
|
8
|
+
names = if defined? @variables_to_freeze
|
9
|
+
@variables_to_freeze.dup
|
10
|
+
else
|
11
|
+
[]
|
12
|
+
end
|
13
|
+
names += superclass.variables_to_freeze if superclass.respond_to? :variables_to_freeze
|
14
|
+
names
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def freeze_variable(name, &block)
|
19
|
+
ivar = :"@#{name}"
|
20
|
+
if defined? @variables_to_freeze
|
21
|
+
@variables_to_freeze << [ivar, block]
|
22
|
+
else
|
23
|
+
@variables_to_freeze = [[ivar, block]]
|
24
|
+
define_method :freeze_variables do
|
25
|
+
next if frozen?
|
26
|
+
self.class.variables_to_freeze.each do |(ivar, block)|
|
27
|
+
variable = instance_variable_get ivar
|
28
|
+
block.call(variable) unless block.nil?
|
29
|
+
variable.freeze
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def freeze_variables(*names)
|
36
|
+
names.each do |name|
|
37
|
+
freeze_variable name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module InstanceMethods
|
42
|
+
def freeze
|
43
|
+
freeze_variables if respond_to? :freeze_variables
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ParamsReady
|
2
|
+
module Extensions
|
3
|
+
module Hash
|
4
|
+
refine ::Hash do
|
5
|
+
def deep_merge(other)
|
6
|
+
merger = proc { |_, v1, v2| ::Hash === v1 && ::Hash === v2 ? v1.merge(v2, &merger) : v2 }
|
7
|
+
merge(other, &merger)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.try_deep_freeze(object)
|
12
|
+
if object.is_a? ::Hash
|
13
|
+
object.values.each do |value|
|
14
|
+
try_deep_freeze(value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
object.freeze
|
18
|
+
object
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.acts_as_hash?(object)
|
22
|
+
return false unless object.respond_to? :[]
|
23
|
+
return false unless object.respond_to? :key?
|
24
|
+
return false unless object.respond_to? :fetch
|
25
|
+
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.indifferent_access(hash, key, default)
|
30
|
+
hash.fetch(key) do
|
31
|
+
case key
|
32
|
+
when String
|
33
|
+
hash.fetch(key.to_sym, default)
|
34
|
+
when Symbol
|
35
|
+
hash.fetch(key.to_s, default)
|
36
|
+
else
|
37
|
+
string_key = key.to_s
|
38
|
+
hash.fetch(string_key) do
|
39
|
+
hash.fetch(string_key.to_sym, default)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative '../error'
|
2
|
+
|
3
|
+
module ParamsReady
|
4
|
+
module Extensions
|
5
|
+
module LateInit
|
6
|
+
def late_init(
|
7
|
+
name,
|
8
|
+
obligatory: true,
|
9
|
+
freeze: true,
|
10
|
+
getter: true,
|
11
|
+
boolean: false,
|
12
|
+
once: true,
|
13
|
+
definite: true,
|
14
|
+
&block
|
15
|
+
)
|
16
|
+
ivar = :"@#{name}"
|
17
|
+
define_method "set_#{name}" do |value|
|
18
|
+
raise ParamsReadyError, "Can't initialize '#{name}' to nil" if value.nil? && definite
|
19
|
+
value = instance_exec(value, &block) unless block.nil?
|
20
|
+
next if value == Extensions::Undefined
|
21
|
+
|
22
|
+
current = instance_variable_get ivar
|
23
|
+
raise ParamsReadyError, "Variable '#{name}' already set" unless current.nil? || !once
|
24
|
+
value.freeze if freeze
|
25
|
+
instance_variable_set "@#{name}", value
|
26
|
+
end
|
27
|
+
|
28
|
+
if boolean
|
29
|
+
define_method "#{name}?" do
|
30
|
+
instance_variable_get ivar
|
31
|
+
end
|
32
|
+
end
|
33
|
+
attr_reader name if getter
|
34
|
+
obligatory! name if obligatory
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ParamsReady
|
2
|
+
module Extensions
|
3
|
+
module Registry
|
4
|
+
def registry(registry_name, name_method: nil, as: nil, getter: false, &block)
|
5
|
+
class_variable_name = "@@#{registry_name}"
|
6
|
+
|
7
|
+
class_variable_set class_variable_name, {}
|
8
|
+
if as
|
9
|
+
if name_method.nil?
|
10
|
+
define_singleton_method "register_#{as}" do |name, entry|
|
11
|
+
registry = class_variable_get class_variable_name
|
12
|
+
raise ParamsReadyError, "Name '#{name}' already taken for '#{human_string(as)}'" if registry.key? name
|
13
|
+
instance_exec name, entry, &block unless block.nil?
|
14
|
+
registry[name] = entry
|
15
|
+
end
|
16
|
+
else
|
17
|
+
define_singleton_method "register_#{as}" do |entry|
|
18
|
+
name = entry.send name_method
|
19
|
+
registry = class_variable_get class_variable_name
|
20
|
+
raise ParamsReadyError, "Name '#{name}' already taken for '#{human_string(as)}'" if registry.key? name
|
21
|
+
instance_exec name, entry, &block unless block.nil?
|
22
|
+
registry[name] = entry
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
if getter
|
27
|
+
define_singleton_method as do |name|
|
28
|
+
registry = class_variable_get class_variable_name
|
29
|
+
raise ParamsReadyError, "Name '#{name}' not found in #{human_string(registry_name)}" unless registry.key? name
|
30
|
+
registry[name]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
define_singleton_method "has_#{as}?" do |name|
|
34
|
+
registry = class_variable_get class_variable_name
|
35
|
+
registry.key? name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def human_string(string)
|
40
|
+
string.to_s.gsub("_", " ")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ParamsReady
|
2
|
+
module Extensions
|
3
|
+
class Undefined
|
4
|
+
def self.dup
|
5
|
+
self
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.present?
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.blank?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.value_indefinite?(value)
|
17
|
+
value == self || value.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
freeze
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'set'
|
2
|
+
require_relative 'error'
|
3
|
+
require_relative 'helpers/rule'
|
4
|
+
|
5
|
+
module ParamsReady
|
6
|
+
class Format
|
7
|
+
module Wrapper
|
8
|
+
attr_reader :format
|
9
|
+
|
10
|
+
extend Forwardable
|
11
|
+
def_delegators :format,
|
12
|
+
:alternative?,
|
13
|
+
:standard?,
|
14
|
+
:hash_key,
|
15
|
+
:marshal,
|
16
|
+
:marshal?,
|
17
|
+
:remap?,
|
18
|
+
:local?,
|
19
|
+
:name
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :marshal, :naming_scheme, :name, :hash
|
23
|
+
|
24
|
+
OMIT_ALL = %i(undefined nil default no_output).freeze
|
25
|
+
def initialize(marshal:, naming_scheme:, remap:, omit:, local:, name: nil)
|
26
|
+
@marshal = Helpers::Rule(marshal)
|
27
|
+
@naming_scheme = naming_scheme
|
28
|
+
@remap = remap
|
29
|
+
@omit = omit.to_set.freeze
|
30
|
+
@local = local
|
31
|
+
@name = name.nil? ? name : name.to_sym
|
32
|
+
@hash = [@marshal, @naming_scheme, @remap, @omit, @local, @name].hash
|
33
|
+
freeze
|
34
|
+
end
|
35
|
+
|
36
|
+
def ==(other)
|
37
|
+
return false unless other.is_a? Format
|
38
|
+
return true if self.object_id == other.object_id
|
39
|
+
return false unless marshal == other.marshal
|
40
|
+
return false unless naming_scheme == other.naming_scheme
|
41
|
+
return false unless remap? == other.remap?
|
42
|
+
return false unless @omit == other.instance_variable_get(:@omit)
|
43
|
+
return false unless local? == other.local?
|
44
|
+
return false unless name == other.name
|
45
|
+
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def alternative?
|
50
|
+
@naming_scheme == :alternative
|
51
|
+
end
|
52
|
+
|
53
|
+
def standard?
|
54
|
+
@naming_scheme == :standard
|
55
|
+
end
|
56
|
+
|
57
|
+
def remap?
|
58
|
+
@remap
|
59
|
+
end
|
60
|
+
|
61
|
+
def hash_key(parameter)
|
62
|
+
case @naming_scheme
|
63
|
+
when :standard then parameter.name
|
64
|
+
when :alternative then parameter.altn
|
65
|
+
else
|
66
|
+
raise ParamsReadyError, "Unexpected option: #{@naming_scheme}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def omit?(parameter)
|
71
|
+
return true if parameter.no_output?(self)
|
72
|
+
return true if parameter.is_undefined? && @omit.member?(:undefined)
|
73
|
+
return true if parameter.is_nil? && @omit.member?(:nil)
|
74
|
+
return true if parameter.is_default? && @omit.member?(:default)
|
75
|
+
false
|
76
|
+
end
|
77
|
+
|
78
|
+
def local?
|
79
|
+
@local
|
80
|
+
end
|
81
|
+
|
82
|
+
def preserve?(parameter)
|
83
|
+
!omit?(parameter)
|
84
|
+
end
|
85
|
+
|
86
|
+
def marshal?(type)
|
87
|
+
@marshal.include?(type)
|
88
|
+
end
|
89
|
+
|
90
|
+
def update(**opts)
|
91
|
+
opts = instance_variables.reject { |ivar| ivar == :@hash }.map do |ivar|
|
92
|
+
value = instance_variable_get(ivar)
|
93
|
+
name = ivar.to_s.gsub(/^@/, '').to_sym
|
94
|
+
[name, value]
|
95
|
+
end.to_h.merge(opts)
|
96
|
+
|
97
|
+
Format.new(**opts)
|
98
|
+
end
|
99
|
+
|
100
|
+
@names = {
|
101
|
+
backend: Format.new(marshal: :none, omit: [], naming_scheme: :standard, remap: false, local: true, name: :backend),
|
102
|
+
frontend: Format.new(marshal: :all, omit: OMIT_ALL, naming_scheme: :alternative, remap: false, local: false, name: :frontend),
|
103
|
+
create: Format.new(marshal: :none, omit: [], naming_scheme: :standard, remap: false, local: true, name: :create),
|
104
|
+
update: Format.new(marshal: :none, omit: %i(undefined), naming_scheme: :standard, remap: false, local: true, name: :update),
|
105
|
+
json: Format.new(marshal: { except: [:array, :tuple, :boolean, :number] }, omit: [], naming_scheme: :alternative, remap: true, local: false, name: :json),
|
106
|
+
inspect: Format.new(marshal: :none, omit: [], naming_scheme: :standard, remap: false, local: false, name: :inspect)
|
107
|
+
}.freeze
|
108
|
+
|
109
|
+
def self.define(name, format)
|
110
|
+
@names = @names.dup
|
111
|
+
@names[name] = format
|
112
|
+
@names.freeze
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.instance(name)
|
116
|
+
raise ParamsReadyError, "Unknown format '#{name}'" unless @names.key? name
|
117
|
+
@names[name]
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.resolve(format_or_name)
|
121
|
+
if format_or_name.is_a? Format
|
122
|
+
format_or_name
|
123
|
+
elsif format_or_name.is_a? Symbol
|
124
|
+
instance(format_or_name)
|
125
|
+
elsif format_or_name.respond_to? :format
|
126
|
+
format_or_name.format
|
127
|
+
else
|
128
|
+
raise ParamsReadyError, "Not an acceptable format: #{format_or_name}"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|