appfuel 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +25 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +19 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +9 -0
- data/README.md +38 -0
- data/Rakefile +6 -0
- data/appfuel.gemspec +42 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/lib/appfuel.rb +210 -0
- data/lib/appfuel/application.rb +4 -0
- data/lib/appfuel/application/app_container.rb +223 -0
- data/lib/appfuel/application/container_class_registration.rb +22 -0
- data/lib/appfuel/application/container_key.rb +201 -0
- data/lib/appfuel/application/qualify_container_key.rb +76 -0
- data/lib/appfuel/application/root.rb +140 -0
- data/lib/appfuel/cli_msg_request.rb +19 -0
- data/lib/appfuel/configuration.rb +14 -0
- data/lib/appfuel/configuration/definition_dsl.rb +175 -0
- data/lib/appfuel/configuration/file_loader.rb +61 -0
- data/lib/appfuel/configuration/populate.rb +95 -0
- data/lib/appfuel/configuration/search.rb +45 -0
- data/lib/appfuel/db_model.rb +16 -0
- data/lib/appfuel/domain.rb +7 -0
- data/lib/appfuel/domain/criteria.rb +436 -0
- data/lib/appfuel/domain/domain_name_parser.rb +44 -0
- data/lib/appfuel/domain/dsl.rb +247 -0
- data/lib/appfuel/domain/entity.rb +242 -0
- data/lib/appfuel/domain/entity_collection.rb +87 -0
- data/lib/appfuel/domain/expr.rb +127 -0
- data/lib/appfuel/domain/value_object.rb +7 -0
- data/lib/appfuel/errors.rb +104 -0
- data/lib/appfuel/feature.rb +2 -0
- data/lib/appfuel/feature/action_loader.rb +25 -0
- data/lib/appfuel/feature/initializer.rb +43 -0
- data/lib/appfuel/handler.rb +6 -0
- data/lib/appfuel/handler/action.rb +17 -0
- data/lib/appfuel/handler/base.rb +103 -0
- data/lib/appfuel/handler/command.rb +18 -0
- data/lib/appfuel/handler/inject_dsl.rb +88 -0
- data/lib/appfuel/handler/validator_dsl.rb +256 -0
- data/lib/appfuel/initialize.rb +70 -0
- data/lib/appfuel/initialize/initializer.rb +68 -0
- data/lib/appfuel/msg_request.rb +207 -0
- data/lib/appfuel/predicates.rb +10 -0
- data/lib/appfuel/presenter.rb +18 -0
- data/lib/appfuel/presenter/base.rb +7 -0
- data/lib/appfuel/repository.rb +73 -0
- data/lib/appfuel/repository/base.rb +72 -0
- data/lib/appfuel/repository/initializer.rb +19 -0
- data/lib/appfuel/repository/mapper.rb +203 -0
- data/lib/appfuel/repository/mapping_dsl.rb +210 -0
- data/lib/appfuel/repository/mapping_entry.rb +76 -0
- data/lib/appfuel/repository/mapping_registry.rb +121 -0
- data/lib/appfuel/repository_runner.rb +60 -0
- data/lib/appfuel/request.rb +53 -0
- data/lib/appfuel/response.rb +96 -0
- data/lib/appfuel/response_handler.rb +79 -0
- data/lib/appfuel/root_module.rb +31 -0
- data/lib/appfuel/run_error.rb +9 -0
- data/lib/appfuel/storage.rb +3 -0
- data/lib/appfuel/storage/db.rb +4 -0
- data/lib/appfuel/storage/db/active_record_model.rb +42 -0
- data/lib/appfuel/storage/db/mapper.rb +213 -0
- data/lib/appfuel/storage/db/migration_initializer.rb +42 -0
- data/lib/appfuel/storage/db/migration_runner.rb +15 -0
- data/lib/appfuel/storage/db/migration_tasks.rb +18 -0
- data/lib/appfuel/storage/db/repository.rb +231 -0
- data/lib/appfuel/storage/db/repository_query.rb +13 -0
- data/lib/appfuel/storage/file.rb +1 -0
- data/lib/appfuel/storage/file/base.rb +32 -0
- data/lib/appfuel/storage/memory.rb +2 -0
- data/lib/appfuel/storage/memory/mapper.rb +30 -0
- data/lib/appfuel/storage/memory/repository.rb +37 -0
- data/lib/appfuel/types.rb +53 -0
- data/lib/appfuel/validation.rb +80 -0
- data/lib/appfuel/validation/validator.rb +59 -0
- data/lib/appfuel/validation/validator_pipe.rb +47 -0
- data/lib/appfuel/version.rb +3 -0
- metadata +335 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
module Appfuel
|
2
|
+
module Domain
|
3
|
+
|
4
|
+
module DomainNameParser
|
5
|
+
|
6
|
+
# This parse the domain name string or object with domain_name method
|
7
|
+
# and returns an array with feature, domain and name.
|
8
|
+
# @example
|
9
|
+
# parse_domain_name('Foo.Bar.Baz')
|
10
|
+
# ['Foo', 'Bar', 'Foo.Bar.Baz']
|
11
|
+
# @param name [String, Object] domain name
|
12
|
+
# @return [Array] parsed Array from domain name
|
13
|
+
def parse_domain_name(name)
|
14
|
+
if !name.is_a?(String) && !name.respond_to?(:domain_name)
|
15
|
+
fail 'domain name must be a string or implement method :domain_name'
|
16
|
+
end
|
17
|
+
|
18
|
+
name = name.domain_name if name.respond_to?(:domain_name)
|
19
|
+
feature, domain = name.split('.')
|
20
|
+
if domain.nil?
|
21
|
+
domain, feature = feature, nil
|
22
|
+
end
|
23
|
+
|
24
|
+
[feature, domain, name]
|
25
|
+
end
|
26
|
+
|
27
|
+
# This parse the domain attributes string and returns an array with
|
28
|
+
# two elements.
|
29
|
+
# @example
|
30
|
+
# parse_domain_attr('Foo.Bar.Baz')
|
31
|
+
# ['Foo.Bar', 'Baz']
|
32
|
+
# @param name [String] domain name attributes
|
33
|
+
# @return [Array] parsed Array from domain attributes
|
34
|
+
def parse_domain_attr(name)
|
35
|
+
unless name.is_a?(String)
|
36
|
+
fail 'domain attribute name must be a string'
|
37
|
+
end
|
38
|
+
|
39
|
+
*first, last = name.split('.')
|
40
|
+
[first.join('.'), last]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
module Appfuel
|
2
|
+
# Mixin used to add attributes to an object. Attributes are given an name
|
3
|
+
# and have a type declaration which is used to ensure it is correct. Types
|
4
|
+
# are handled by Dry::Types which are mixed into the Types module. When an
|
5
|
+
# object is instaniated dymamic getters and setters are created depending
|
6
|
+
# on if the a value_object flag has been toggled
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# attribute :foo, 'strict.string', default: 'bar', min_size: 3
|
10
|
+
#
|
11
|
+
module Domain
|
12
|
+
module Dsl
|
13
|
+
# Class macro dsl used to implement attributes
|
14
|
+
attr_accessor :equalizer
|
15
|
+
attr_reader :schema, :defaults
|
16
|
+
protected :equalizer=
|
17
|
+
|
18
|
+
def self.extended(base)
|
19
|
+
base.instance_variable_set(:@schema, {})
|
20
|
+
base.instance_variable_set(:@value_object, false)
|
21
|
+
end
|
22
|
+
|
23
|
+
def inherited(klass)
|
24
|
+
super
|
25
|
+
klass.instance_variable_set(:@value_object, false)
|
26
|
+
klass.instance_variable_set(:@schema, {})
|
27
|
+
klass.equalizer = Dry::Equalizer.new(*schema.keys)
|
28
|
+
klass.send(:include, klass.equalizer)
|
29
|
+
|
30
|
+
register_container_class(klass)
|
31
|
+
Types.register_domain(klass)
|
32
|
+
end
|
33
|
+
|
34
|
+
def default?
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
def valid?(value)
|
39
|
+
self === value
|
40
|
+
end
|
41
|
+
|
42
|
+
def value_object?
|
43
|
+
@value_object
|
44
|
+
end
|
45
|
+
|
46
|
+
def enable_value_object
|
47
|
+
@value_object = true
|
48
|
+
end
|
49
|
+
|
50
|
+
def disable_value_object
|
51
|
+
@value_object = false
|
52
|
+
end
|
53
|
+
|
54
|
+
def type(str)
|
55
|
+
Types[str]
|
56
|
+
end
|
57
|
+
|
58
|
+
def strict_enum(*args)
|
59
|
+
type('strict.string').enum(*args)
|
60
|
+
end
|
61
|
+
|
62
|
+
def enum(*args)
|
63
|
+
type('coercible.string').enum(*args)
|
64
|
+
end
|
65
|
+
|
66
|
+
def attribute_names
|
67
|
+
schema.keys
|
68
|
+
end
|
69
|
+
|
70
|
+
def attribute(name, type_str, **options)
|
71
|
+
unless type_str.is_a?(String)
|
72
|
+
return handle_manual_type(name, type_str, options)
|
73
|
+
end
|
74
|
+
|
75
|
+
name = name.to_sym
|
76
|
+
type = build_type(type_str, options)
|
77
|
+
schema[name] = type unless attribute_exists?(name, type)
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def build_type(type_str, **options)
|
82
|
+
base = type_str.split('.').last
|
83
|
+
type = Types[type_str]
|
84
|
+
type = apply_defaults(type, options)
|
85
|
+
type = apply_optional(type, options)
|
86
|
+
|
87
|
+
nil_is_allowed = allow_nil?(options)
|
88
|
+
|
89
|
+
type = case base
|
90
|
+
when 'hash' then handle_hash(type, options)
|
91
|
+
when 'array' then handle_array(type, options)
|
92
|
+
else
|
93
|
+
type
|
94
|
+
end
|
95
|
+
|
96
|
+
type = apply_constraints(type, options)
|
97
|
+
|
98
|
+
# You have to apply all the contraints before summing nil
|
99
|
+
type = sum_nil(type) if nil_is_allowed
|
100
|
+
|
101
|
+
type
|
102
|
+
end
|
103
|
+
|
104
|
+
def attribute_exists?(name, type)
|
105
|
+
schema[name.to_sym] === type
|
106
|
+
end
|
107
|
+
|
108
|
+
def attribute_conflict?(name, type)
|
109
|
+
name = name.to_sym
|
110
|
+
schema.key?(name) && schema[name] != type
|
111
|
+
end
|
112
|
+
|
113
|
+
def create(inputs = {})
|
114
|
+
self.new(inputs)
|
115
|
+
end
|
116
|
+
|
117
|
+
alias_method :call, :create
|
118
|
+
alias_method :[], :create
|
119
|
+
|
120
|
+
def try(input)
|
121
|
+
Dry::Types::Result::Success.new(self[input])
|
122
|
+
rescue => e
|
123
|
+
failure = Dry::Types::Result::Failure.new(input, e.message)
|
124
|
+
block_given? ? yield(failure) : failure
|
125
|
+
end
|
126
|
+
|
127
|
+
def domain_name
|
128
|
+
@domain_name ||= build_domain_name
|
129
|
+
end
|
130
|
+
|
131
|
+
def domain_basename
|
132
|
+
domain_name.split('.').last
|
133
|
+
end
|
134
|
+
|
135
|
+
def empty_hash(undefined_as_nil = false)
|
136
|
+
data = {}
|
137
|
+
value = undefined_as_nil == true ? nil : Types::Undefined
|
138
|
+
schema.keys.each do |key|
|
139
|
+
data[key] = value
|
140
|
+
end
|
141
|
+
data
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def parse_class_name
|
147
|
+
return ["anonmous_#{generate_code(6)}"] if name.nil?
|
148
|
+
name.underscore.split('/')
|
149
|
+
end
|
150
|
+
|
151
|
+
def build_domain_name
|
152
|
+
"#{container_feature_name}.#{container_key_basename}"
|
153
|
+
end
|
154
|
+
|
155
|
+
def generate_code(nbr)
|
156
|
+
charset = Array('A' .. 'Z') + Array('a' .. 'z')
|
157
|
+
Array.new(nbr) { charset.sample }.join
|
158
|
+
end
|
159
|
+
|
160
|
+
def handle_manual_type(name, type, options)
|
161
|
+
name = name.to_sym
|
162
|
+
type = apply_defaults(type, options)
|
163
|
+
if attribute_conflict?(name, type)
|
164
|
+
fail RuntimeError, "Attribute :#{name} has already been defined " +
|
165
|
+
"as another type"
|
166
|
+
end
|
167
|
+
|
168
|
+
schema[name] = type unless attribute_exists?(name, type)
|
169
|
+
end
|
170
|
+
|
171
|
+
def handle_hash(type, options)
|
172
|
+
return type unless options.key?(:hash)
|
173
|
+
constructor = options.fetch(:constructor) { :schema }
|
174
|
+
options.delete(:constructor)
|
175
|
+
valid = [
|
176
|
+
:schema,
|
177
|
+
:weak,
|
178
|
+
:permissive,
|
179
|
+
:strict,
|
180
|
+
:strict_with_defaults,
|
181
|
+
:symbolized
|
182
|
+
]
|
183
|
+
|
184
|
+
unless valid.include?(constructor)
|
185
|
+
fail "the :constructor of the hash must be one of the " +
|
186
|
+
"following (#{valid.join(' ')})"
|
187
|
+
end
|
188
|
+
|
189
|
+
unless options[:hash].is_a?(Hash)
|
190
|
+
fail ":hash params must be a hash"
|
191
|
+
end
|
192
|
+
|
193
|
+
if options[:hash].empty?
|
194
|
+
fail ":hash params that are empty don't make sense you probably " +
|
195
|
+
"want to exclude the params and use the constructor alone"
|
196
|
+
end
|
197
|
+
|
198
|
+
hash = options.delete(:hash)
|
199
|
+
params = {}
|
200
|
+
hash.each do |key, value|
|
201
|
+
params[key] = value.is_a?(String) ? Types[value] : value
|
202
|
+
end
|
203
|
+
type.send(constructor, params)
|
204
|
+
end
|
205
|
+
|
206
|
+
def handle_array(type, options)
|
207
|
+
if options.key?(:member)
|
208
|
+
member = options.delete(:member)
|
209
|
+
member = member.is_a?(String) ? Types[member] : member
|
210
|
+
type = type.member(member)
|
211
|
+
end
|
212
|
+
type
|
213
|
+
end
|
214
|
+
|
215
|
+
def apply_defaults(type, options)
|
216
|
+
return type unless options.key?(:default)
|
217
|
+
|
218
|
+
type.default(options.delete(:default))
|
219
|
+
end
|
220
|
+
|
221
|
+
def apply_optional(type, options)
|
222
|
+
return type unless options.key?(:optional)
|
223
|
+
|
224
|
+
options.delete(:optional)
|
225
|
+
type.optional
|
226
|
+
end
|
227
|
+
|
228
|
+
def apply_constraints(type, options)
|
229
|
+
return type if options.empty?
|
230
|
+
type.constrained(options)
|
231
|
+
end
|
232
|
+
|
233
|
+
def allow_nil?(options)
|
234
|
+
result = false
|
235
|
+
if options.key?(:allow_nil)
|
236
|
+
options.delete(:allow_nil)
|
237
|
+
result = true
|
238
|
+
end
|
239
|
+
result
|
240
|
+
end
|
241
|
+
|
242
|
+
def sum_nil(type)
|
243
|
+
type | Types['strict.nil']
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
module Appfuel
|
2
|
+
# Mixin used to add attributes to an object. Attributes are given an name
|
3
|
+
# and have a type declaration which is used to ensure it is correct. Types
|
4
|
+
# are handled by Dry::Types which are mixed into the Types module. When an
|
5
|
+
# object is instaniated dymamic getters and setters are created depending
|
6
|
+
# on if the a value_object flag has been toggled
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# attribute :foo, 'strict.string', default: 'bar', min_size: 3
|
10
|
+
#
|
11
|
+
module Domain
|
12
|
+
class Entity
|
13
|
+
extend Appfuel::Application::ContainerKey
|
14
|
+
extend Appfuel::Application::ContainerClassRegistration
|
15
|
+
extend Dsl
|
16
|
+
|
17
|
+
def initialize(inputs = {})
|
18
|
+
setup_attributes(inputs)
|
19
|
+
enable_undefined
|
20
|
+
@is_global = domain_name.count('.') == 0
|
21
|
+
|
22
|
+
rescue Dry::Types::ConstraintError => e
|
23
|
+
msg = "#{self.class.name} could not initialize: #{e.message}"
|
24
|
+
error = RuntimeError.new(msg)
|
25
|
+
error.set_backtrace(e.backtrace)
|
26
|
+
raise error
|
27
|
+
end
|
28
|
+
|
29
|
+
def global?
|
30
|
+
@is_global
|
31
|
+
end
|
32
|
+
|
33
|
+
def collection?
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
def hide_undefined?
|
38
|
+
@hide_undefined
|
39
|
+
end
|
40
|
+
|
41
|
+
def hide_undefined
|
42
|
+
@hide_undefined = true
|
43
|
+
end
|
44
|
+
|
45
|
+
def show_undefined
|
46
|
+
@hide_undefined = false
|
47
|
+
end
|
48
|
+
|
49
|
+
def enable_undefined
|
50
|
+
show_undefined
|
51
|
+
@undefined_as_nil = false
|
52
|
+
each_entity do |entity|
|
53
|
+
entity.enable_undefined
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def undefined_as_nil
|
58
|
+
@undefined_as_nil = true
|
59
|
+
each_entity do |entity|
|
60
|
+
entity.undefined_as_nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def undefined_as_nil?
|
65
|
+
@undefined_as_nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def attr_typed!(name, value)
|
69
|
+
self.class.schema[name][value]
|
70
|
+
end
|
71
|
+
|
72
|
+
def data_typed!(type_name, value)
|
73
|
+
data_type(type_name)[value]
|
74
|
+
end
|
75
|
+
|
76
|
+
def data_type(type_name)
|
77
|
+
self.class.type(type_name)
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate_type!(value, type_str, **options)
|
81
|
+
type = self.class.build_type(type_str, **options)
|
82
|
+
type[value]
|
83
|
+
end
|
84
|
+
|
85
|
+
def domain_name
|
86
|
+
self.class.domain_name
|
87
|
+
end
|
88
|
+
|
89
|
+
def domain_basename
|
90
|
+
self.class.domain_basename
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_hash
|
94
|
+
data = {}
|
95
|
+
self.class.schema.each do |key, type|
|
96
|
+
fail "no getter defined for #{key}" unless respond_to?(key)
|
97
|
+
value = send(key)
|
98
|
+
case
|
99
|
+
when value.is_a?(Array)
|
100
|
+
list = []
|
101
|
+
value.each do |item|
|
102
|
+
list << (item.is_a?(Entity) ? item.to_hash : item)
|
103
|
+
end
|
104
|
+
value = list
|
105
|
+
when value.is_a?(Hash)
|
106
|
+
dict = {}
|
107
|
+
value.each do |value_key, item|
|
108
|
+
dict[value_key] = item.is_a?(Entity) ? item.to_hash : item
|
109
|
+
end
|
110
|
+
value = dict
|
111
|
+
when value.respond_to?(:to_hash)
|
112
|
+
value = value.to_hash
|
113
|
+
when value == Types::Undefined
|
114
|
+
if type.respond_to?(:domain_name)
|
115
|
+
value = type.empty_hash(undefined_as_nil? ? true : false)
|
116
|
+
end
|
117
|
+
next if hide_undefined?
|
118
|
+
|
119
|
+
end
|
120
|
+
data[key] = value
|
121
|
+
end
|
122
|
+
data.deep_symbolize_keys
|
123
|
+
end
|
124
|
+
|
125
|
+
def to_h
|
126
|
+
to_hash
|
127
|
+
end
|
128
|
+
|
129
|
+
def has?(key)
|
130
|
+
value = send(key)
|
131
|
+
!value.nil? && value != Types::Undefined
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def each_attr_schema
|
137
|
+
self.class.schema.each do |key, type|
|
138
|
+
yield key, type
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def each_entity
|
143
|
+
each_attr_schema do |key, type|
|
144
|
+
if type.respond_to?(:<) && type < Dsl && has?(key)
|
145
|
+
yield send(key)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def each_attr
|
151
|
+
each_attr_schema do |key, type|
|
152
|
+
yield key, send(key)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def value_object?
|
157
|
+
self.class.value_object?
|
158
|
+
end
|
159
|
+
|
160
|
+
def setup_attributes(inputs = {})
|
161
|
+
inputs = {} if inputs.nil?
|
162
|
+
inputs = inputs.to_h if inputs == self
|
163
|
+
|
164
|
+
unless inputs.is_a?(Hash)
|
165
|
+
fail "Can not create #{self} entity inputs must be a Hash"
|
166
|
+
end
|
167
|
+
|
168
|
+
inputs.deep_symbolize_keys!
|
169
|
+
self.class.schema.each do |key, type|
|
170
|
+
value = Types::Undefined
|
171
|
+
value = inputs[key] if inputs.key?(key)
|
172
|
+
if value_object?
|
173
|
+
setup_value_object(key, type, value)
|
174
|
+
next
|
175
|
+
end
|
176
|
+
setup_entity(key, type, value)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def setup_value_object(key, type, input)
|
181
|
+
define_getter(key)
|
182
|
+
initialize_value(key, type, input)
|
183
|
+
freeze_instance_var(key)
|
184
|
+
end
|
185
|
+
|
186
|
+
def setup_entity(key, type, input)
|
187
|
+
define_getter(key)
|
188
|
+
initialize_value(key, type, input)
|
189
|
+
define_setter(key, type)
|
190
|
+
end
|
191
|
+
|
192
|
+
def initialize_value(key, type, input)
|
193
|
+
if input == Types::Undefined && type.default?
|
194
|
+
input = type[nil]
|
195
|
+
end
|
196
|
+
|
197
|
+
# manual overrides have to manually type check themselves
|
198
|
+
setter = "#{key}="
|
199
|
+
return send(setter, input) if respond_to?(setter)
|
200
|
+
|
201
|
+
if input != Types::Undefined && input != nil
|
202
|
+
input = type[input]
|
203
|
+
end
|
204
|
+
|
205
|
+
instance_variable_set("@#{key}", input)
|
206
|
+
rescue => e
|
207
|
+
msg = "#{domain_name} could not assign :#{key} #{e.message}"
|
208
|
+
error = RuntimeError.new(msg)
|
209
|
+
error.set_backtrace(e.backtrace)
|
210
|
+
raise error
|
211
|
+
end
|
212
|
+
|
213
|
+
def define_getter(key)
|
214
|
+
return if respond_to?(key)
|
215
|
+
define_singleton_method(key) do
|
216
|
+
value = instance_variable_get("@#{key}")
|
217
|
+
value = nil if value == Types::Undefined && undefined_as_nil?
|
218
|
+
value
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def define_setter(key, type)
|
223
|
+
setter = "#{key}="
|
224
|
+
return if respond_to?(setter)
|
225
|
+
|
226
|
+
define_singleton_method(setter) do |input|
|
227
|
+
value = is_entity?(input, type) ? input : type[input]
|
228
|
+
instance_variable_set("@#{key}", value)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def freeze_instance_var(key)
|
233
|
+
instance_variable_get("@#{key}").freeze
|
234
|
+
end
|
235
|
+
|
236
|
+
|
237
|
+
def is_entity?(value, type)
|
238
|
+
value.respond_to?(:domain_name) && value.domain_name == type.domain_name
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|