params_ready 0.0.1
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.rb +36 -0
- data/lib/params_ready/builder.rb +140 -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 +15 -0
- data/lib/params_ready/format.rb +130 -0
- data/lib/params_ready/helpers/arel_builder.rb +68 -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/key_map.rb +176 -0
- data/lib/params_ready/helpers/memo.rb +42 -0
- data/lib/params_ready/helpers/options.rb +39 -0
- data/lib/params_ready/helpers/parameter_definer_class_methods.rb +39 -0
- data/lib/params_ready/helpers/parameter_storage_class_methods.rb +36 -0
- data/lib/params_ready/helpers/parameter_user_class_methods.rb +31 -0
- data/lib/params_ready/helpers/relation_builder_wrapper.rb +35 -0
- data/lib/params_ready/helpers/rule.rb +57 -0
- data/lib/params_ready/helpers/storage.rb +30 -0
- data/lib/params_ready/helpers/usage_rule.rb +18 -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/hash_marshallers.rb +100 -0
- data/lib/params_ready/marshaller/hash_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/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 +127 -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_hash_parameter.rb +204 -0
- data/lib/params_ready/parameter/array_parameter.rb +197 -0
- data/lib/params_ready/parameter/definition.rb +264 -0
- data/lib/params_ready/parameter/hash_parameter.rb +63 -0
- data/lib/params_ready/parameter/hash_set_parameter.rb +101 -0
- data/lib/params_ready/parameter/parameter.rb +456 -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/tuple_parameter.rb +152 -0
- data/lib/params_ready/parameter/value_parameter.rb +182 -0
- data/lib/params_ready/parameter_definer.rb +14 -0
- data/lib/params_ready/parameter_user.rb +43 -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 +181 -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 +68 -0
- metadata +181 -0
@@ -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,130 @@
|
|
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
|
+
attributes: Format.new(marshal: :none, omit: %i(undefined), naming_scheme: :standard, remap: false, local: true, name: :attributes),
|
104
|
+
json: Format.new(marshal: { except: [:array, :tuple, :boolean, :number] }, omit: [], naming_scheme: :alternative, remap: true, local: false, name: :json)
|
105
|
+
}.freeze
|
106
|
+
|
107
|
+
def self.define(name, format)
|
108
|
+
@names = @names.dup
|
109
|
+
@names[name] = format
|
110
|
+
@names.freeze
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.instance(name)
|
114
|
+
raise ParamsReadyError, "Unknown format '#{name}'" unless @names.key? name
|
115
|
+
@names[name]
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.resolve(format_or_name)
|
119
|
+
if format_or_name.is_a? Format
|
120
|
+
format_or_name
|
121
|
+
elsif format_or_name.is_a? Symbol
|
122
|
+
instance(format_or_name)
|
123
|
+
elsif format_or_name.respond_to? :format
|
124
|
+
format_or_name.format
|
125
|
+
else
|
126
|
+
raise ParamsReadyError, "Not an acceptable format: #{format_or_name}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -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,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
|