params_ready 0.0.1
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.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,172 @@
|
|
1
|
+
require_relative 'parameter'
|
2
|
+
require_relative 'polymorph_parameter'
|
3
|
+
require_relative 'value_parameter'
|
4
|
+
require_relative '../marshaller/parameter_module'
|
5
|
+
require_relative '../marshaller/definition_module'
|
6
|
+
require_relative '../marshaller/builder_module'
|
7
|
+
require_relative '../marshaller/polymorph_marshallers'
|
8
|
+
|
9
|
+
module ParamsReady
|
10
|
+
module Parameter
|
11
|
+
class PolymorphParameter < Parameter
|
12
|
+
include ComplexParameter
|
13
|
+
include Marshaller::ParameterModule
|
14
|
+
|
15
|
+
def_delegators :@definition, :identifier, :types
|
16
|
+
intent_for_children :restriction
|
17
|
+
|
18
|
+
def permission_depends_on
|
19
|
+
type = to_type
|
20
|
+
return [] if type.nil?
|
21
|
+
[type]
|
22
|
+
end
|
23
|
+
|
24
|
+
def set_value_as(value, type, context = Format.instance(:backend), validator = nil)
|
25
|
+
parameter = types[type].create
|
26
|
+
parameter.set_value value, context, validator
|
27
|
+
@value = parameter
|
28
|
+
end
|
29
|
+
|
30
|
+
def type
|
31
|
+
return nil unless is_definite?
|
32
|
+
bare_value.name
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_type
|
36
|
+
bare_value
|
37
|
+
end
|
38
|
+
|
39
|
+
def [](key)
|
40
|
+
raise ParamsReadyError, "Type '#{key}' is not set, current type: nil" if is_nil?
|
41
|
+
|
42
|
+
param = bare_value
|
43
|
+
if param.name != key
|
44
|
+
raise ParamsReadyError, "Type '#{key}' is not set, current type: '#{param.name}'"
|
45
|
+
else
|
46
|
+
param
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def child_for_update(path)
|
53
|
+
type, *path = path
|
54
|
+
[self[type], type, path]
|
55
|
+
end
|
56
|
+
|
57
|
+
def updated_clone(_child_name, updated)
|
58
|
+
clone = definition.create
|
59
|
+
clone.populate_with(updated, frozen?)
|
60
|
+
clone
|
61
|
+
end
|
62
|
+
|
63
|
+
def populate_with(value, freeze = false)
|
64
|
+
@value = if freeze && value.frozen?
|
65
|
+
value
|
66
|
+
else
|
67
|
+
value.dup
|
68
|
+
end
|
69
|
+
|
70
|
+
self.freeze if freeze
|
71
|
+
self
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class PolymorphParameterBuilder < Builder
|
76
|
+
include Marshaller::BuilderModule
|
77
|
+
|
78
|
+
register :polymorph
|
79
|
+
|
80
|
+
def self.instance(name, altn: nil)
|
81
|
+
new PolymorphParameterDefinition.new(name, altn: altn)
|
82
|
+
end
|
83
|
+
|
84
|
+
def type(input, *args, **opts, &block)
|
85
|
+
definition = self.class.resolve(input, *args, **opts, &block)
|
86
|
+
@definition.add_type definition
|
87
|
+
end
|
88
|
+
|
89
|
+
def identifier(identifier)
|
90
|
+
@definition.set_identifier identifier
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class PolymorphParameterDefinition < Definition
|
95
|
+
include ValueParameterDefinition::ValueLike
|
96
|
+
include Marshaller::DefinitionModule[Marshaller::PolymorphMarshallers.collection]
|
97
|
+
|
98
|
+
obligatory! :types
|
99
|
+
attr_reader :types
|
100
|
+
# late_init :identifier, obligatory: true
|
101
|
+
|
102
|
+
parameter_class PolymorphParameter
|
103
|
+
name_for_formatter :polymorph
|
104
|
+
|
105
|
+
def initialize(*args, identifier: nil, types: [], default_name: nil, **options)
|
106
|
+
@types = {}
|
107
|
+
@alt_names = {}
|
108
|
+
add_types types
|
109
|
+
set_default(default_name)
|
110
|
+
super *args, **options
|
111
|
+
set_identifier identifier unless identifier.nil?
|
112
|
+
end
|
113
|
+
|
114
|
+
def add_type(definition)
|
115
|
+
check_type_names(definition)
|
116
|
+
raise ParamsReadyError, "Reused name: #{definition.name}" if @types.key? definition.name
|
117
|
+
raise ParamsReadyError, "Reused alternative: #{definition.altn}" if @alt_names.key? definition.altn
|
118
|
+
@types[definition.name] = definition
|
119
|
+
@alt_names[definition.altn] = definition
|
120
|
+
end
|
121
|
+
|
122
|
+
def check_type_names(definition)
|
123
|
+
return if @marshallers.nil?
|
124
|
+
return unless @marshallers.default?
|
125
|
+
default = @marshallers.default
|
126
|
+
return unless default.respond_to? :reserved?
|
127
|
+
|
128
|
+
raise ParamsReadyError, "Reserved name: #{definition.name}" if default.reserved?(definition.name)
|
129
|
+
raise ParamsReadyError, "Reserved alternative: #{definition.altn}" if default.reserved?(definition.altn)
|
130
|
+
end
|
131
|
+
|
132
|
+
def add_types(types)
|
133
|
+
return if types.nil?
|
134
|
+
types.each do |definition|
|
135
|
+
add_type definition
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def set_identifier(type_identifier)
|
140
|
+
raise ParamsReadyError, "Identifier already taken: #{type_identifier}" if @alt_names&.key?(type_identifier)
|
141
|
+
raise ParamsReadyError, "Identifier already taken: #{type_identifier}" if @types&.key?(type_identifier)
|
142
|
+
set_marshaller using: :hash, type_identifier: type_identifier
|
143
|
+
end
|
144
|
+
|
145
|
+
def type(name, context)
|
146
|
+
name = if context.alternative?
|
147
|
+
@alt_names[name.to_sym].name
|
148
|
+
else
|
149
|
+
name
|
150
|
+
end
|
151
|
+
@types[name.to_sym]
|
152
|
+
end
|
153
|
+
|
154
|
+
def set_default(default_name)
|
155
|
+
return if default_name.nil?
|
156
|
+
|
157
|
+
type_def = types[default_name]
|
158
|
+
raise ParamsReadyError, "Unknown type '#{default_name}'" if type_def.nil?
|
159
|
+
raise ParamsReadyError, "Default type must have default" unless type_def.default_defined?
|
160
|
+
frozen = freeze_value(type_def.create)
|
161
|
+
@default = frozen
|
162
|
+
end
|
163
|
+
|
164
|
+
def finish
|
165
|
+
set_identifier :ppt unless marshallers.default?
|
166
|
+
super
|
167
|
+
end
|
168
|
+
|
169
|
+
freeze_variables :types
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require_relative '../error'
|
2
|
+
require_relative '../../params_ready/parameter/hash_parameter'
|
3
|
+
require_relative '../query/relation'
|
4
|
+
|
5
|
+
module ParamsReady
|
6
|
+
module Parameter
|
7
|
+
class State < HashParameter
|
8
|
+
extend Query::Relation::PageAccessors
|
9
|
+
extend Forwardable
|
10
|
+
def_delegators :definition, :relations
|
11
|
+
|
12
|
+
def relation(name)
|
13
|
+
raise ParamsReadyError, "Relation not defined: '#{name}'" unless relations.include? name
|
14
|
+
child(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.relation_delegator(name)
|
18
|
+
define_method name do |relation_name, *args|
|
19
|
+
relation(relation_name).send(name, *args)
|
20
|
+
end
|
21
|
+
ruby2_keywords name
|
22
|
+
end
|
23
|
+
|
24
|
+
relation_delegator :ordering
|
25
|
+
relation_delegator :num_pages
|
26
|
+
relation_delegator :page_no
|
27
|
+
relation_delegator :offset
|
28
|
+
relation_delegator :limit
|
29
|
+
relation_delegator :has_previous?
|
30
|
+
relation_delegator :has_previous?
|
31
|
+
relation_delegator :has_next?
|
32
|
+
relation_delegator :has_page?
|
33
|
+
|
34
|
+
def page(relation_name = nil, delta = 0, count: nil)
|
35
|
+
if delta == 0
|
36
|
+
clone
|
37
|
+
else
|
38
|
+
raise ParamsReadyError, "Relation must be specified when delta is not 0" if relation_name.nil?
|
39
|
+
|
40
|
+
return nil unless relation(relation_name).pagination.can_yield_page? delta, count: count
|
41
|
+
new_offset = relation(relation_name).new_offset(delta)
|
42
|
+
update_in(new_offset, [relation_name, :pagination, 0])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def current_page
|
47
|
+
page
|
48
|
+
end
|
49
|
+
|
50
|
+
def first_page(relation_name)
|
51
|
+
value = relation(relation_name).pagination.first_page_value
|
52
|
+
update_in(value, [relation_name, :pagination])
|
53
|
+
end
|
54
|
+
|
55
|
+
def last_page(relation_name, *args, **opts)
|
56
|
+
value = relation(relation_name).pagination.last_page_value(*args, **opts)
|
57
|
+
return if value.nil?
|
58
|
+
update_in(value, [relation_name, :pagination])
|
59
|
+
end
|
60
|
+
|
61
|
+
def previous_page(relation_name, delta = 1)
|
62
|
+
value = relation(relation_name).pagination.previous_page_value(delta)
|
63
|
+
return if value.nil?
|
64
|
+
update_in(value, [relation_name, :pagination])
|
65
|
+
end
|
66
|
+
|
67
|
+
def next_page(relation_name, delta = 1, count: nil)
|
68
|
+
value = relation(relation_name).pagination.next_page_value(delta, count: count)
|
69
|
+
return if value.nil?
|
70
|
+
update_in(value, [relation_name, :pagination])
|
71
|
+
end
|
72
|
+
|
73
|
+
def before_page(relation_name, keyset)
|
74
|
+
value = relation(relation_name).pagination.before_page_value(keyset)
|
75
|
+
update_in(value, [relation_name, :pagination])
|
76
|
+
end
|
77
|
+
|
78
|
+
def after_page(relation_name, keyset)
|
79
|
+
value = relation(relation_name).pagination.after_page_value(keyset)
|
80
|
+
update_in(value, [relation_name, :pagination])
|
81
|
+
end
|
82
|
+
|
83
|
+
def limited_at(relation_name, limit)
|
84
|
+
limit_key = relation(relation_name).pagination.limit_key
|
85
|
+
update_in(limit, [relation_name, :pagination, limit_key])
|
86
|
+
end
|
87
|
+
|
88
|
+
def toggled_order(relation_name, column)
|
89
|
+
new_order = relation(relation_name).ordering.toggled_order_value(column)
|
90
|
+
toggled = update_in(new_order, [relation_name, :ordering])
|
91
|
+
toggled.first_page(relation_name)
|
92
|
+
end
|
93
|
+
|
94
|
+
def reordered(relation_name, column, direction)
|
95
|
+
new_order = relation(relation_name).ordering.reordered_value(column, direction)
|
96
|
+
reordered = update_in(new_order, [relation_name, :ordering])
|
97
|
+
reordered.first_page(relation_name)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class StateBuilder < HashParameterBuilder
|
102
|
+
def relation(relation)
|
103
|
+
@definition.add_relation relation
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.instance
|
107
|
+
definition = StateDefinition.new(:'', altn: :'')
|
108
|
+
new definition
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class StateDefinition < HashParameterDefinition
|
113
|
+
parameter_class State
|
114
|
+
attr_reader :relations
|
115
|
+
|
116
|
+
def initialize(*args, **opts)
|
117
|
+
super *args, **opts
|
118
|
+
@relations = Set.new
|
119
|
+
end
|
120
|
+
|
121
|
+
def add_relation(relation)
|
122
|
+
if @relations.include? relation.name
|
123
|
+
raise ParamsReadyError, "Relation already there '#{relation.name}'"
|
124
|
+
end
|
125
|
+
@relations << relation.name
|
126
|
+
add_child relation
|
127
|
+
end
|
128
|
+
|
129
|
+
freeze_variable :relations
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'set'
|
2
|
+
require_relative 'parameter'
|
3
|
+
require_relative '../builder'
|
4
|
+
require_relative 'definition'
|
5
|
+
require_relative 'array_parameter'
|
6
|
+
require_relative '../marshaller/tuple_marshallers'
|
7
|
+
require_relative '../marshaller/definition_module'
|
8
|
+
require_relative '../marshaller/builder_module'
|
9
|
+
require_relative '../marshaller/parameter_module'
|
10
|
+
|
11
|
+
module ParamsReady
|
12
|
+
module Parameter
|
13
|
+
class TupleParameter < Parameter
|
14
|
+
include ArrayParameter::ArrayLike
|
15
|
+
include Marshaller::ParameterModule
|
16
|
+
|
17
|
+
def_delegators :@definition, :names, :fields, :separator, :marshaller
|
18
|
+
|
19
|
+
freeze_variable :value do |array|
|
20
|
+
next if Extensions::Undefined.value_indefinite?(array)
|
21
|
+
array.each(&:freeze)
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(name, *args)
|
25
|
+
integer = ordinal_to_integer(name)
|
26
|
+
if integer.nil?
|
27
|
+
super
|
28
|
+
else
|
29
|
+
self[integer - 1]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def respond_to_missing?(name, include_private = false)
|
34
|
+
return true unless ordinal_to_integer(name).nil?
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def element(index)
|
41
|
+
return nil if is_nil?
|
42
|
+
|
43
|
+
value = bare_value
|
44
|
+
if index < 0 || index >= value.length
|
45
|
+
raise ParamsReadyError, "Index out of bounds: #{index}"
|
46
|
+
else
|
47
|
+
value[index]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
ORDINALS = %i{
|
52
|
+
first second third fourth fifth sixth seventh eighth nineth tenth
|
53
|
+
}.each_with_index.map do |ordinal, index|
|
54
|
+
[ordinal, index + 1]
|
55
|
+
end.to_h.freeze
|
56
|
+
|
57
|
+
def ordinal_to_integer(name)
|
58
|
+
integer = ORDINALS[name]
|
59
|
+
return nil if integer.nil?
|
60
|
+
return nil if definition.arity < integer
|
61
|
+
|
62
|
+
integer
|
63
|
+
end
|
64
|
+
|
65
|
+
def init_value
|
66
|
+
@value = []
|
67
|
+
fields.each do |definition|
|
68
|
+
@value << definition.create
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class TupleParameterBuilder < Builder
|
74
|
+
include Marshaller::BuilderModule
|
75
|
+
register :tuple
|
76
|
+
|
77
|
+
def self.instance(name, altn: nil)
|
78
|
+
new TupleParameterDefinition.new(name, altn: altn)
|
79
|
+
end
|
80
|
+
|
81
|
+
def field(input, *args, **opts, &block)
|
82
|
+
definition = self.class.resolve(input, *args, **opts, &block)
|
83
|
+
@definition.add_field definition
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class TupleParameterDefinition < Definition
|
88
|
+
include ArrayParameterDefinition::ArrayLike
|
89
|
+
include Marshaller::DefinitionModule[Marshaller::TupleMarshallers.collection]
|
90
|
+
|
91
|
+
class StringMarshaller
|
92
|
+
def initialize(separator:)
|
93
|
+
@separator = separator
|
94
|
+
end
|
95
|
+
|
96
|
+
def marshal(fields, _format)
|
97
|
+
fields.join(@separator)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class HashMarshaller
|
102
|
+
def marshal(fields, _format)
|
103
|
+
fields.each_with_index.map do |field, index|
|
104
|
+
[index.to_s, field]
|
105
|
+
end.to_h
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
name_for_formatter :tuple
|
110
|
+
|
111
|
+
parameter_class TupleParameter
|
112
|
+
|
113
|
+
def initialize(*args, separator: nil, fields: nil, **options)
|
114
|
+
@fields = []
|
115
|
+
add_fields fields unless fields.nil?
|
116
|
+
super *args, **options
|
117
|
+
end
|
118
|
+
|
119
|
+
def add_fields(fields)
|
120
|
+
fields.each do |field|
|
121
|
+
add_field(field)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
collection :fields, :field do |field|
|
126
|
+
raise ParamsReadyError, "Can't add field if default is present" if default_defined?
|
127
|
+
raise ParamsReadyError, "Not a field definition #{field.class.name}" unless field.is_a? AbstractDefinition
|
128
|
+
raise ParamsReadyError, "Field is not a value #{field.class.name}" unless field.is_a? ValueParameterDefinition
|
129
|
+
raise ParamsReadyError, "Field can't be optional" if field.optional?
|
130
|
+
raise ParamsReadyError, "Field can't have default" if field.default_defined?
|
131
|
+
field
|
132
|
+
end
|
133
|
+
|
134
|
+
def arity
|
135
|
+
@fields.length
|
136
|
+
end
|
137
|
+
|
138
|
+
def ensure_canonical(array)
|
139
|
+
raise ParamsReadyError, "Not an array" unless array.is_a? Array
|
140
|
+
context = Format.instance(:backend)
|
141
|
+
marshaller = marshallers.instance(Array)
|
142
|
+
value, _validator = marshaller.canonicalize(self, array, context, nil, freeze: true)
|
143
|
+
value
|
144
|
+
end
|
145
|
+
|
146
|
+
def freeze
|
147
|
+
@fields.freeze
|
148
|
+
super
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|