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.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/lib/arel/cte_name.rb +20 -0
  3. data/lib/params_ready/builder.rb +161 -0
  4. data/lib/params_ready/error.rb +31 -0
  5. data/lib/params_ready/extensions/class_reader_writer.rb +33 -0
  6. data/lib/params_ready/extensions/collection.rb +43 -0
  7. data/lib/params_ready/extensions/delegation.rb +25 -0
  8. data/lib/params_ready/extensions/finalizer.rb +26 -0
  9. data/lib/params_ready/extensions/freezer.rb +49 -0
  10. data/lib/params_ready/extensions/hash.rb +46 -0
  11. data/lib/params_ready/extensions/late_init.rb +38 -0
  12. data/lib/params_ready/extensions/registry.rb +44 -0
  13. data/lib/params_ready/extensions/undefined.rb +23 -0
  14. data/lib/params_ready/format.rb +132 -0
  15. data/lib/params_ready/helpers/arel_builder.rb +68 -0
  16. data/lib/params_ready/helpers/callable.rb +14 -0
  17. data/lib/params_ready/helpers/conditional_block.rb +31 -0
  18. data/lib/params_ready/helpers/find_in_hash.rb +22 -0
  19. data/lib/params_ready/helpers/interface_definer.rb +48 -0
  20. data/lib/params_ready/helpers/key_map.rb +176 -0
  21. data/lib/params_ready/helpers/memo.rb +41 -0
  22. data/lib/params_ready/helpers/options.rb +107 -0
  23. data/lib/params_ready/helpers/parameter_definer_class_methods.rb +39 -0
  24. data/lib/params_ready/helpers/parameter_storage_class_methods.rb +63 -0
  25. data/lib/params_ready/helpers/parameter_user_class_methods.rb +35 -0
  26. data/lib/params_ready/helpers/relation_builder_wrapper.rb +35 -0
  27. data/lib/params_ready/helpers/rule.rb +76 -0
  28. data/lib/params_ready/helpers/storage.rb +30 -0
  29. data/lib/params_ready/helpers/usage_rule.rb +36 -0
  30. data/lib/params_ready/input_context.rb +31 -0
  31. data/lib/params_ready/intent.rb +70 -0
  32. data/lib/params_ready/marshaller/array_marshallers.rb +132 -0
  33. data/lib/params_ready/marshaller/builder_module.rb +9 -0
  34. data/lib/params_ready/marshaller/collection.rb +165 -0
  35. data/lib/params_ready/marshaller/definition_module.rb +63 -0
  36. data/lib/params_ready/marshaller/enum_set_marshallers.rb +96 -0
  37. data/lib/params_ready/marshaller/parameter_module.rb +11 -0
  38. data/lib/params_ready/marshaller/polymorph_marshallers.rb +67 -0
  39. data/lib/params_ready/marshaller/struct_marshallers.rb +100 -0
  40. data/lib/params_ready/marshaller/tuple_marshallers.rb +103 -0
  41. data/lib/params_ready/ordering/column.rb +60 -0
  42. data/lib/params_ready/ordering/ordering.rb +276 -0
  43. data/lib/params_ready/output_parameters.rb +138 -0
  44. data/lib/params_ready/pagination/abstract_pagination.rb +18 -0
  45. data/lib/params_ready/pagination/cursor.rb +171 -0
  46. data/lib/params_ready/pagination/direction.rb +148 -0
  47. data/lib/params_ready/pagination/keyset_pagination.rb +254 -0
  48. data/lib/params_ready/pagination/keysets.rb +70 -0
  49. data/lib/params_ready/pagination/nulls.rb +31 -0
  50. data/lib/params_ready/pagination/offset_pagination.rb +130 -0
  51. data/lib/params_ready/pagination/tendency.rb +28 -0
  52. data/lib/params_ready/parameter/abstract_struct_parameter.rb +204 -0
  53. data/lib/params_ready/parameter/array_parameter.rb +197 -0
  54. data/lib/params_ready/parameter/definition.rb +272 -0
  55. data/lib/params_ready/parameter/enum_set_parameter.rb +102 -0
  56. data/lib/params_ready/parameter/parameter.rb +475 -0
  57. data/lib/params_ready/parameter/polymorph_parameter.rb +172 -0
  58. data/lib/params_ready/parameter/state.rb +132 -0
  59. data/lib/params_ready/parameter/struct_parameter.rb +64 -0
  60. data/lib/params_ready/parameter/tuple_parameter.rb +152 -0
  61. data/lib/params_ready/parameter/value_parameter.rb +186 -0
  62. data/lib/params_ready/parameter_definer.rb +14 -0
  63. data/lib/params_ready/parameter_user.rb +35 -0
  64. data/lib/params_ready/query/array_grouping.rb +68 -0
  65. data/lib/params_ready/query/custom_predicate.rb +102 -0
  66. data/lib/params_ready/query/exists_predicate.rb +103 -0
  67. data/lib/params_ready/query/fixed_operator_predicate.rb +77 -0
  68. data/lib/params_ready/query/grouping.rb +177 -0
  69. data/lib/params_ready/query/join_clause.rb +87 -0
  70. data/lib/params_ready/query/nullness_predicate.rb +71 -0
  71. data/lib/params_ready/query/polymorph_predicate.rb +77 -0
  72. data/lib/params_ready/query/predicate.rb +203 -0
  73. data/lib/params_ready/query/predicate_operator.rb +132 -0
  74. data/lib/params_ready/query/relation.rb +337 -0
  75. data/lib/params_ready/query/structured_grouping.rb +58 -0
  76. data/lib/params_ready/query/variable_operator_predicate.rb +125 -0
  77. data/lib/params_ready/query_context.rb +21 -0
  78. data/lib/params_ready/restriction.rb +252 -0
  79. data/lib/params_ready/result.rb +109 -0
  80. data/lib/params_ready/value/coder.rb +210 -0
  81. data/lib/params_ready/value/constraint.rb +198 -0
  82. data/lib/params_ready/value/custom.rb +56 -0
  83. data/lib/params_ready/value/validator.rb +81 -0
  84. data/lib/params_ready/version.rb +7 -0
  85. data/lib/params_ready.rb +28 -0
  86. metadata +227 -0
@@ -0,0 +1,76 @@
1
+ require 'set'
2
+
3
+ module ParamsReady
4
+ module Helpers
5
+ def self.Rule(input)
6
+ return input if input.nil?
7
+ return input if input.is_a? Rule
8
+
9
+ Rule.instance(input).freeze
10
+ end
11
+
12
+ class Rule
13
+ attr_reader :hash, :mode, :values
14
+
15
+ def self.instance(input)
16
+ mode, values = case input
17
+ when :none, :all then [input, nil]
18
+ when Hash
19
+ if input.length > 1 || input.length < 1
20
+ raise ParamsReadyError, "Unexpected hash for rule: '#{input}'"
21
+ end
22
+ key, values = input.first
23
+ case key
24
+ when :except, :only then [key, values.to_set.freeze]
25
+ else
26
+ raise ParamsReadyError, "Unexpected mode for rule: '#{key}'"
27
+ end
28
+ else
29
+ raise ParamsReadyError, "Unexpected input for rule: '#{input}'"
30
+ end
31
+ new(mode, values)
32
+ end
33
+
34
+ def initialize(mode, values)
35
+ @mode = mode
36
+ @values = values.freeze
37
+ @hash = [@mode, @values].hash
38
+ freeze
39
+ end
40
+
41
+ def merge(other)
42
+ return self if other.nil?
43
+ raise ParamsReadyError, "Can't merge with #{other.class.name}" unless other.is_a? Rule
44
+ raise ParamsReadyError, "Can't merge incompatible rules: #{mode}/#{other.mode}" if other.mode != mode
45
+
46
+ case mode
47
+ when :all, :none
48
+ self
49
+ when :only, :except
50
+ values = self.values + other.values
51
+ Rule.new(mode, values)
52
+ end
53
+ end
54
+
55
+ def include?(name)
56
+ case @mode
57
+ when :none then false
58
+ when :all then true
59
+ when :only then @values.member? name
60
+ when :except
61
+ !@values.member? name
62
+ else
63
+ raise ParamsReadyError, "Unexpected mode for rule: '#{@mode}'"
64
+ end
65
+ end
66
+
67
+ def ==(other)
68
+ return false unless other.is_a? Rule
69
+ return true if object_id == other.object_id
70
+ return false unless @mode == other.instance_variable_get(:@mode)
71
+
72
+ @values == other.instance_variable_get(:@values)
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,30 @@
1
+ module ParamsReady
2
+ module Helpers
3
+ class Storage
4
+ attr_reader :parameters, :relations
5
+
6
+ def initialize
7
+ @parameters = Hash.new
8
+ @relations = Hash.new
9
+ end
10
+
11
+ def has_relation?(name)
12
+ relations.key? name
13
+ end
14
+
15
+ def has_parameter?(name)
16
+ parameters.key? name
17
+ end
18
+
19
+ def add_relation(relation)
20
+ raise ParamsReadyError, "Relation already exists: #{relation.name}" if self.has_relation?(relation.name)
21
+ @relations[relation.name] = relation
22
+ end
23
+
24
+ def add_parameter(param)
25
+ raise ParamsReadyError, "Parameter already exists: #{param.name}" if self.has_parameter?(param.name)
26
+ @parameters[param.name] = param
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,36 @@
1
+ require_relative 'rule'
2
+
3
+ module ParamsReady
4
+ module Helpers
5
+ class UsageRule
6
+ attr_reader :parameter_definition, :rule
7
+
8
+ def initialize(parameter_definition, rule = :all)
9
+ @parameter_definition = parameter_definition
10
+ @rule = ParamsReady::Helpers::Rule(rule)
11
+ freeze
12
+ end
13
+
14
+ def valid_for?(method)
15
+ @rule.include? method
16
+ end
17
+
18
+ def name
19
+ parameter_definition.name
20
+ end
21
+
22
+ def merge(other)
23
+ return self if other.nil?
24
+ raise ParamsReadyError, "Can't merge into #{other.class.name}" unless other.is_a? UsageRule
25
+
26
+ unless parameter_definition == other.parameter_definition
27
+ message = "Can't merge incompatible rules: #{parameter_definition.name}/#{other.parameter_definition.name}"
28
+ raise ParamsReadyError, message
29
+ end
30
+
31
+ rule = self.rule.merge(other.rule)
32
+ UsageRule.new(parameter_definition, rule)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,31 @@
1
+ require 'forwardable'
2
+ require_relative 'format'
3
+
4
+ module ParamsReady
5
+ class InputContext
6
+ include Format::Wrapper
7
+ extend Forwardable
8
+
9
+ attr_reader :data
10
+
11
+ def_delegator :data, :[]
12
+
13
+ def initialize(format, data = {})
14
+ @format = Format.resolve(format).freeze
15
+ @data = data.freeze
16
+ end
17
+
18
+ def self.resolve(unknown)
19
+ case unknown
20
+ when nil
21
+ Format.instance(:frontend)
22
+ when InputContext, Format
23
+ unknown
24
+ when Symbol
25
+ Format.instance(unknown)
26
+ else
27
+ raise ParamsReadyError, "Unexpected type for InputContext: #{unknown.class.name}"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,70 @@
1
+ require 'forwardable'
2
+ require_relative 'restriction'
3
+ require_relative 'format'
4
+ require_relative 'parameter/parameter'
5
+
6
+ module ParamsReady
7
+ class Intent
8
+ extend Forwardable
9
+ include Restriction::Wrapper
10
+ include Format::Wrapper
11
+
12
+ def clone(restriction:)
13
+ Intent.new @format, restriction, data: @data
14
+ end
15
+
16
+ attr_reader :data, :hash
17
+
18
+ def initialize(format, restriction = Restriction.blanket_permission, data: nil)
19
+ @format = Format.resolve(format).freeze
20
+ raise ParamsReadyError, "Restriction expected, got: #{restriction.inspect}" unless restriction.is_a? Restriction
21
+ @restriction = restriction
22
+ @data = check_data(data)
23
+ @hash = [@format, @restriction, @data].hash
24
+ freeze
25
+ end
26
+
27
+ def check_data(data)
28
+ return if data.nil?
29
+ # The reason we require data object to be
30
+ # a Parameter is that it must be deep frozen
31
+ # for the output memoizing feature to work properly.
32
+ raise 'Data object must be a parameter' unless data.is_a? Parameter::Parameter
33
+ raise 'Data object must be frozen' unless data.frozen?
34
+
35
+ data
36
+ end
37
+
38
+ def omit?(parameter)
39
+ return true unless permitted?(parameter)
40
+ @format.omit?(parameter)
41
+ end
42
+
43
+ def preserve?(parameter)
44
+ !omit?(parameter)
45
+ end
46
+
47
+ def self.instance(name)
48
+ format = Format.instance(name)
49
+ Intent.new(format)
50
+ end
51
+
52
+ def self.resolve(intent_or_name)
53
+ if intent_or_name.is_a? Intent
54
+ intent_or_name
55
+ else
56
+ instance(intent_or_name)
57
+ end
58
+ end
59
+
60
+ def ==(other)
61
+ return false unless other.is_a?(Intent)
62
+ return true if object_id == other.object_id
63
+ restriction == other.restriction && format == other.format && data == other.data
64
+ end
65
+
66
+ def eql?(other)
67
+ self == other
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,132 @@
1
+ require_relative 'collection'
2
+ require_relative '../extensions/undefined'
3
+ require_relative '../extensions/hash'
4
+ require_relative '../helpers/find_in_hash'
5
+
6
+ module ParamsReady
7
+ module Marshaller
8
+ class ArrayMarshallers
9
+ module AbstractMarshaller
10
+ def marshal(parameter, intent)
11
+ array = parameter.send(:bare_value)
12
+ definition = parameter.definition
13
+ compact = definition.compact?
14
+
15
+ elements = array.map do |element|
16
+ if element.eligible_for_output?(intent)
17
+ element.format_self_permitted(intent)
18
+ end
19
+ end
20
+ elements = elements.compact if compact
21
+ do_marshal(elements, intent, compact)
22
+ end
23
+ end
24
+
25
+ module ArrayMarshaller
26
+ extend AbstractMarshaller
27
+
28
+ def self.canonicalize(definition, array, context, validator, freeze: false)
29
+ canonical = array.map do |value|
30
+ next if definition.compact? && value.nil?
31
+
32
+ element = definition.prototype.create
33
+ element.set_from_input(value, context, validator)
34
+ next if definition.compact? && element.is_nil?
35
+
36
+ element.freeze if freeze
37
+ element
38
+ end.compact
39
+
40
+ [canonical, validator]
41
+ end
42
+
43
+ def self.do_marshal(array, _, _)
44
+ array
45
+ end
46
+
47
+ freeze
48
+ end
49
+
50
+ module StructMarshaller
51
+ extend AbstractMarshaller
52
+
53
+ def self.canonicalize(definition, hash, context, validator)
54
+ if definition.compact?
55
+ ArrayMarshaller.canonicalize(definition, hash.values, context, validator)
56
+ else
57
+ count_key = :cnt
58
+ found, count = Helpers::FindInHash.find_in_hash hash, count_key
59
+ raise ParamsReadyError, "Count not found" unless found
60
+
61
+ count = Integer(count)
62
+ array = (0...count).map do |index|
63
+ found, value = Helpers::FindInHash.find_in_hash hash, index
64
+ element = definition.prototype.create
65
+ element.set_from_input(value, context, validator) if found
66
+ element
67
+ end
68
+ [array, validator]
69
+ end
70
+ end
71
+
72
+ def self.do_marshal(array, _, compact)
73
+ return array if compact
74
+
75
+ result = array.each_with_index.reduce({}) do |result, (element, index)|
76
+ index = index.to_s
77
+ result[index] = element
78
+ result
79
+ end
80
+
81
+ result['cnt'] = array.length.to_s
82
+ result
83
+ end
84
+
85
+ freeze
86
+ end
87
+
88
+ class StringMarshaller
89
+ include AbstractMarshaller
90
+
91
+ attr_reader :separator
92
+
93
+ def self.instance(separator:, split_pattern: nil)
94
+ instance = new separator, split_pattern
95
+ [String, instance.freeze]
96
+ end
97
+
98
+ def initialize(separator, split_pattern)
99
+ @separator = separator.to_s.freeze
100
+ @split_pattern = split_pattern.freeze
101
+ end
102
+
103
+ def split_pattern
104
+ @split_pattern || @separator
105
+ end
106
+
107
+ def canonicalize(definition, string, context, validator)
108
+ array = string.split(split_pattern).map(&:strip).reject(&:empty?)
109
+ ArrayMarshaller.canonicalize(definition, array, context, validator)
110
+ end
111
+
112
+ def do_marshal(array, _, _)
113
+ array.join(separator)
114
+ end
115
+
116
+ freeze
117
+ end
118
+
119
+ def self.collection
120
+ @collection ||= begin
121
+ c = ClassCollection.new Array
122
+ c.add_instance Array, ArrayMarshaller
123
+ c.add_instance Hash, StructMarshaller
124
+ c.add_factory :string, StringMarshaller
125
+ c.default!(Hash)
126
+ c.freeze
127
+ c
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,9 @@
1
+ module ParamsReady
2
+ module Marshaller
3
+ module BuilderModule
4
+ def marshal(to: nil, using: nil, **opts)
5
+ @definition.set_marshaller(to: to, using: using, **opts)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,165 @@
1
+ require_relative '../error'
2
+ require_relative '../extensions/hash'
3
+
4
+ module ParamsReady
5
+ module Marshaller
6
+ class InstanceCollection
7
+ attr_reader :default, :instances
8
+
9
+ def initialize(canonical, default = nil, instances = {})
10
+ @canonical = canonical
11
+ @default = default
12
+ @instances = instances
13
+ end
14
+
15
+ def canonicalize(definition, input, context, validator, **opts)
16
+ value_class = infer_class(input)
17
+ marshaller = instance(value_class)
18
+ raise ParamsReadyError, "Unexpected type for #{definition.name}: #{value_class.name}" if marshaller.nil?
19
+
20
+ marshaller.canonicalize(definition, input, context, validator, **opts)
21
+ end
22
+
23
+ def marshal_canonical(parameter, format, **opts)
24
+ marshaller = instance @canonical
25
+ if marshaller.nil?
26
+ value = parameter.send(:bare_value)
27
+ raise ParamsReadyError, "Value is not canonical" unless value.is_a? @canonical
28
+ value
29
+ else
30
+ marshaller.marshal(parameter, format, **opts)
31
+ end
32
+ end
33
+
34
+ def marshal(parameter, format, **opts)
35
+ default.marshal(parameter, format, **opts)
36
+ end
37
+
38
+ def infer_class(value)
39
+ if instances.key? value.class
40
+ value.class
41
+ elsif value.is_a?(Hash) || Extensions::Hash.acts_as_hash?(value)
42
+ Hash
43
+ else
44
+ value.class
45
+ end
46
+ end
47
+
48
+ def add_instance(value_class, instance)
49
+ raise ParamsReadyError, "Marshaller must be frozen" unless instance.frozen?
50
+
51
+ @instances[value_class] = instance
52
+ end
53
+
54
+ def instance(value_class)
55
+ @instances[value_class]
56
+ end
57
+
58
+ def instance?(value_class)
59
+ @instances.key?(value_class)
60
+ end
61
+
62
+ def default=(instance)
63
+ raise ParamsReadyError, "Default already defined" if default?
64
+ raise ParamsReadyError, "Marshaller must be frozen" unless instance.frozen?
65
+
66
+ @default = instance
67
+ end
68
+
69
+ def default!(value_class)
70
+ instance = instance(value_class)
71
+ raise ParamsReadyError, "No marshaller for class '#{value_class.name}'" if instance.nil?
72
+ self.default = instance
73
+ end
74
+
75
+ def default?
76
+ !@default.nil?
77
+ end
78
+
79
+ def reverse_merge(other)
80
+ clone = self.class.new(@canonical, @default, @instances.dup)
81
+ populate_clone(clone, other)
82
+ end
83
+
84
+ def populate_clone(clone, other)
85
+ if other.default? && !clone.default?
86
+ clone.default = other.default
87
+ end
88
+
89
+ other.instances.each do |value_class, i|
90
+ next if clone.instance?(value_class)
91
+
92
+ clone.add_instance value_class, i
93
+ end
94
+
95
+ clone
96
+ end
97
+
98
+ def freeze
99
+ @instance.freeze
100
+ super
101
+ end
102
+ end
103
+
104
+ class ClassCollection < InstanceCollection
105
+ attr_reader :factories
106
+
107
+ def initialize(canonical, default = nil, instances = {}, factories = {})
108
+ @factories = factories
109
+ super canonical, default, instances
110
+ end
111
+
112
+ def instance_collection
113
+ InstanceCollection.new(@canonical, nil, @instances.dup)
114
+ end
115
+
116
+ def add_factory(name, factory)
117
+ name = name.to_sym
118
+ raise ParamsReadyError, "Name '#{name}' already taken" if factory?(name)
119
+ raise ParamsReadyError, "Factory must be frozen" unless factory.frozen?
120
+
121
+ @factories[name] = factory
122
+ end
123
+
124
+ def add_instance(value_class, instance)
125
+ raise ParamsReadyError, "Marshaller for '#{value_class.name}' already exists" if instance?(value_class)
126
+
127
+ super
128
+ end
129
+
130
+ def build_instance(name, **opts)
131
+ factory(name).instance(**opts)
132
+ end
133
+
134
+ def factory(name)
135
+ @factories[name]
136
+ end
137
+
138
+ def factory?(name)
139
+ @factories.key? name
140
+ end
141
+
142
+ def freeze
143
+ @factories.freeze
144
+ super
145
+ end
146
+
147
+ def reverse_merge(other)
148
+ clone = self.class.new(@canonical, @default, @instances.dup, @factories.dup)
149
+ populate_clone(clone, other)
150
+ end
151
+
152
+ def populate_clone(clone, other)
153
+ merged = super
154
+
155
+ other.factories.each do |value_class, f|
156
+ next if merged.factory?(value_class)
157
+
158
+ clone.add_factory value_class, f
159
+ end
160
+
161
+ merged
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,63 @@
1
+ module ParamsReady
2
+ module Marshaller
3
+ module DefinitionModule
4
+ def self.[](collection)
5
+ mod = Module.new
6
+ mod.include self
7
+ mod.define_method :class_marshallers do
8
+ collection
9
+ end
10
+ mod
11
+ end
12
+
13
+ attr_reader :marshallers
14
+
15
+ def initialize(*args, marshaller: nil, **options)
16
+ @marshallers = class_marshallers.instance_collection
17
+ set_marshaller(**marshaller) unless marshaller.nil?
18
+
19
+ super *args, **options
20
+ end
21
+
22
+ def set_marshaller(to: nil, using: nil, **opts)
23
+ if using.is_a? Symbol
24
+ raise ParamsReadyError, "Expected ':to' argument to be nil, got #{to.class.name}" unless to.nil?
25
+ default_class, instance = class_marshallers.build_instance(using, **opts)
26
+ @marshallers.add_instance(default_class, instance)
27
+ @marshallers.default!(default_class)
28
+ elsif using.nil?
29
+ @marshallers.default!(to)
30
+ else
31
+ @marshallers.add_instance(to, using)
32
+ @marshallers.default!(to)
33
+ end
34
+ end
35
+
36
+ def marshal(parameter, intent, **opts)
37
+ if intent.marshal?(name_for_formatter)
38
+ @marshallers.marshal(parameter, intent, **opts)
39
+ else
40
+ @marshallers.marshal_canonical(parameter, intent, **opts)
41
+ end
42
+ end
43
+
44
+ def try_canonicalize(input, context, validator = nil, **opts)
45
+ @marshallers.canonicalize(self, input, context, validator, **opts)
46
+ end
47
+
48
+ def finish
49
+ unless @marshallers.default?
50
+ if class_marshallers.default?
51
+ @marshallers.default = class_marshallers.default
52
+ end
53
+ end
54
+ super
55
+ end
56
+
57
+ def freeze
58
+ @marshallers.freeze
59
+ super
60
+ end
61
+ end
62
+ end
63
+ end