appfuel 0.2.0
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/.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
|