reality-model 1.0.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/.gitattributes +6 -0
- data/.gitignore +8 -0
- data/.ruby-version +1 -0
- data/.travis.yml +11 -0
- data/CONTRIBUTING.md +26 -0
- data/Gemfile +5 -0
- data/LICENSE +201 -0
- data/README.md +9 -0
- data/Rakefile +18 -0
- data/lib/reality/model/core.rb +19 -0
- data/lib/reality/model/model_element.rb +202 -0
- data/lib/reality/model/repository.rb +131 -0
- data/lib/reality/model.rb +22 -0
- data/reality-model.gemspec +31 -0
- data/test/helper.rb +25 -0
- data/test/test_model_element.rb +512 -0
- data/test/test_repository.rb +225 -0
- metadata +147 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
#
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
|
+
# you may not use this file except in compliance with the License.
|
4
|
+
# You may obtain a copy of the License at
|
5
|
+
#
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
#
|
8
|
+
# Unless required by applicable law or agreed to in writing, software
|
9
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
10
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
11
|
+
# See the License for the specific language governing permissions and
|
12
|
+
# limitations under the License.
|
13
|
+
#
|
14
|
+
|
15
|
+
require 'reality/logging'
|
16
|
+
require 'reality/naming'
|
17
|
+
require 'reality/options'
|
18
|
+
require 'reality/orderedhash'
|
19
|
+
|
20
|
+
require 'reality/model/core'
|
21
|
+
require 'reality/model/model_element'
|
22
|
+
require 'reality/model/repository'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{reality-model}
|
5
|
+
s.version = '1.0.0'
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
|
8
|
+
s.authors = ['Peter Donald']
|
9
|
+
s.email = %q{peter@realityforge.org}
|
10
|
+
|
11
|
+
s.homepage = %q{https://github.com/realityforge/reality-model}
|
12
|
+
s.summary = %q{Utility classes for defining a domain model.}
|
13
|
+
s.description = %q{Utility classes for defining a domain model.}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
18
|
+
s.default_executable = []
|
19
|
+
s.require_paths = %w(lib)
|
20
|
+
|
21
|
+
s.has_rdoc = false
|
22
|
+
s.rdoc_options = %w(--line-numbers --inline-source --title reality-model)
|
23
|
+
|
24
|
+
s.add_dependency 'reality-core', '>= 1.7.0'
|
25
|
+
s.add_dependency 'reality-naming', '>= 1.6.0'
|
26
|
+
s.add_dependency 'reality-orderedhash', '>= 1.0.0'
|
27
|
+
|
28
|
+
s.add_development_dependency 'reality-facets', '>= 1.3.0'
|
29
|
+
s.add_development_dependency(%q<minitest>, ['= 5.9.1'])
|
30
|
+
s.add_development_dependency(%q<test-unit>, ['= 3.1.5'])
|
31
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'test/unit/assertions'
|
5
|
+
require 'reality/model'
|
6
|
+
require 'reality/facets'
|
7
|
+
|
8
|
+
class Reality::Model::TestCase < Minitest::Test
|
9
|
+
include Test::Unit::Assertions
|
10
|
+
include Reality::Logging::Assertions
|
11
|
+
|
12
|
+
def setup
|
13
|
+
Reality::Model::TestCase.send(:remove_const, :MyContainer) if Reality::Model::TestCase.const_defined?(:MyContainer)
|
14
|
+
Reality::Model::TestCase.module_eval <<-RUBY
|
15
|
+
module MyContainer
|
16
|
+
end
|
17
|
+
RUBY
|
18
|
+
end
|
19
|
+
|
20
|
+
def assert_model_error(expected_message, &block)
|
21
|
+
assert_logging_error(Reality::Model, expected_message) do
|
22
|
+
yield block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,512 @@
|
|
1
|
+
require File.expand_path('../helper', __FILE__)
|
2
|
+
|
3
|
+
class Reality::Model::TestModelElement < Reality::Model::TestCase
|
4
|
+
def test_basic_operation
|
5
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer)
|
6
|
+
element = Reality::Model::ModelElement.new(repository, :entity, nil, {})
|
7
|
+
|
8
|
+
assert_equal element.repository, repository
|
9
|
+
assert_equal element.key, :entity
|
10
|
+
assert_equal element.container_key, nil
|
11
|
+
assert_equal element.model_classname, :Entity
|
12
|
+
assert_equal element.custom_initialize?, false
|
13
|
+
assert_equal element.id_method, :name
|
14
|
+
assert_equal element.access_method, :entities
|
15
|
+
assert_equal element.inverse_access_method, :entity
|
16
|
+
|
17
|
+
assert_equal repository.model_element_by_key?(:entity), true
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_validate_options
|
21
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer)
|
22
|
+
|
23
|
+
assert_model_error("Unknown option ':x' passed to create model element") do
|
24
|
+
Reality::Model::ModelElement.new(repository, :entity, nil, :x => 1)
|
25
|
+
end
|
26
|
+
|
27
|
+
assert_model_error('Unknown options [:x, :z] passed to create model element') do
|
28
|
+
Reality::Model::ModelElement.new(repository, :entity, nil, :x => 1, :z => 1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def test_default_value_of_id_method
|
34
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer, :default_id_method => :key)
|
35
|
+
element = Reality::Model::ModelElement.new(repository, :entity, nil, {})
|
36
|
+
|
37
|
+
assert_equal element.id_method, :key
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_yield
|
41
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer)
|
42
|
+
Reality::Model::ModelElement.new(repository, :entity, nil, {}) do |element|
|
43
|
+
|
44
|
+
assert_equal element.repository, repository
|
45
|
+
assert_equal element.key, :entity
|
46
|
+
assert_equal element.container_key, nil
|
47
|
+
assert_equal element.model_classname, :Entity
|
48
|
+
assert_equal element.custom_initialize?, false
|
49
|
+
assert_equal element.id_method, :name
|
50
|
+
assert_equal element.access_method, :entities
|
51
|
+
assert_equal element.inverse_access_method, :entity
|
52
|
+
|
53
|
+
assert_equal repository.model_element_by_key?(:entity), true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_basic_operation_with_no_defaults
|
58
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer)
|
59
|
+
element = Reality::Model::ModelElement.new(repository, :entity, nil, :model_classname => :MyEntity, :access_method => :ents, :inverse_access_method => :ent, :id_method => :key, :custom_initialize => true)
|
60
|
+
|
61
|
+
assert_equal element.repository, repository
|
62
|
+
assert_equal element.key, :entity
|
63
|
+
assert_equal element.qualified_key, 'MyTypeSystem.entity'
|
64
|
+
assert_equal element.container_key, nil
|
65
|
+
assert_equal element.model_classname, :MyEntity
|
66
|
+
assert_equal element.custom_initialize?, true
|
67
|
+
assert_equal element.id_method, :key
|
68
|
+
assert_equal element.access_method, :ents
|
69
|
+
assert_equal element.inverse_access_method, :ent
|
70
|
+
|
71
|
+
assert_equal repository.model_element_by_key?(:entity), true
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_bad_attributes
|
75
|
+
assert_model_error("Model Element 'MyTypeSystem.Entity' has a key 'Entity' that does not use the underscore naming pattern (i.e. The key should be 'entity').") do
|
76
|
+
Reality::Model::ModelElement.new(Reality::Model::Repository.new(:MyTypeSystem, MyContainer), :Entity, nil, {})
|
77
|
+
end
|
78
|
+
assert_model_error("Model Element 'MyTypeSystem.entity' has a model_classname 'entity' that does not use the pascal case naming pattern (i.e. The model_classname should be 'Entity').") do
|
79
|
+
Reality::Model::ModelElement.new(Reality::Model::Repository.new(:MyTypeSystem, MyContainer), :entity, nil, :model_classname => 'entity')
|
80
|
+
end
|
81
|
+
assert_model_error("Model Element 'MyTypeSystem.entity' has a access_method 'Entity' that does not use the underscore naming pattern (i.e. The access_method should be 'entity').") do
|
82
|
+
Reality::Model::ModelElement.new(Reality::Model::Repository.new(:MyTypeSystem, MyContainer), :entity, nil, :access_method => 'Entity')
|
83
|
+
end
|
84
|
+
assert_model_error("Model Element 'MyTypeSystem.entity' has a inverse_access_method 'Entity' that does not use the underscore naming pattern (i.e. The inverse_access_method should be 'entity').") do
|
85
|
+
Reality::Model::ModelElement.new(Reality::Model::Repository.new(:MyTypeSystem, MyContainer), :entity, nil, :inverse_access_method => 'Entity')
|
86
|
+
end
|
87
|
+
assert_model_error("Model Element 'MyTypeSystem.entity' has a id_method 'Name' that does not use the underscore naming pattern (i.e. The id_method should be 'name').") do
|
88
|
+
Reality::Model::ModelElement.new(Reality::Model::Repository.new(:MyTypeSystem, MyContainer), :entity, nil, :id_method => 'Name')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_bad_container_key
|
93
|
+
assert_model_error("Model Element 'MyTypeSystem.component' defines container as 'bundle' but no such model element exists.") do
|
94
|
+
Reality::Model::ModelElement.new(Reality::Model::Repository.new(:MyTypeSystem, MyContainer), :component, :bundle, {})
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_container_key
|
99
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer)
|
100
|
+
element1 = Reality::Model::ModelElement.new(repository, :bundle, nil, {})
|
101
|
+
element2 = Reality::Model::ModelElement.new(repository, :component, :bundle, {})
|
102
|
+
|
103
|
+
assert_equal element1.key, :bundle
|
104
|
+
assert_equal element1.container_key, nil
|
105
|
+
assert_equal element2.key, :component
|
106
|
+
assert_equal element2.container_key, :bundle
|
107
|
+
|
108
|
+
assert_equal repository.model_element_by_key?(:bundle), true
|
109
|
+
assert_equal repository.model_element_by_key?(:component), true
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_build_child_accessor_code
|
113
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer)
|
114
|
+
element1 = Reality::Model::ModelElement.new(repository, :bundle, nil, {})
|
115
|
+
element2 = Reality::Model::ModelElement.new(repository, :component, :bundle, {})
|
116
|
+
|
117
|
+
code = element1.send(:build_child_accessor_code, element2)
|
118
|
+
assert_equal code, <<CODE
|
119
|
+
|
120
|
+
public
|
121
|
+
|
122
|
+
def component(name, options = {}, &block)
|
123
|
+
Reality::Model::TestCase::MyContainer::Component.new(self, name, options, &block)
|
124
|
+
end
|
125
|
+
|
126
|
+
def component_by_name?(name)
|
127
|
+
!!component_map[name.to_s]
|
128
|
+
end
|
129
|
+
|
130
|
+
def component_by_name(name)
|
131
|
+
component = component_map[name.to_s]
|
132
|
+
raise "No component with name '\#{name}' defined." unless component
|
133
|
+
component
|
134
|
+
end
|
135
|
+
|
136
|
+
def components
|
137
|
+
component_map.values
|
138
|
+
end
|
139
|
+
|
140
|
+
def components?
|
141
|
+
!component_map.empty?
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def register_component(component)
|
147
|
+
Reality::Model::TestCase::MyContainer.error("Attempting to register duplicate component definition with name '\#{name}'") if component_by_name?(component.name)
|
148
|
+
component_map[component.name.to_s] = component
|
149
|
+
end
|
150
|
+
|
151
|
+
def component_map
|
152
|
+
@component_map ||= Reality::OrderedHash.new
|
153
|
+
end
|
154
|
+
CODE
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_build_child_accessor_code_with_custom_initializer
|
158
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer)
|
159
|
+
element1 = Reality::Model::ModelElement.new(repository, :bundle, nil, {})
|
160
|
+
element2 = Reality::Model::ModelElement.new(repository, :component, :bundle, :custom_initialize => true)
|
161
|
+
|
162
|
+
code = element1.send(:build_child_accessor_code, element2)
|
163
|
+
assert_equal code, <<CODE
|
164
|
+
|
165
|
+
public
|
166
|
+
|
167
|
+
def component_by_name?(name)
|
168
|
+
!!component_map[name.to_s]
|
169
|
+
end
|
170
|
+
|
171
|
+
def component_by_name(name)
|
172
|
+
component = component_map[name.to_s]
|
173
|
+
raise "No component with name '\#{name}' defined." unless component
|
174
|
+
component
|
175
|
+
end
|
176
|
+
|
177
|
+
def components
|
178
|
+
component_map.values
|
179
|
+
end
|
180
|
+
|
181
|
+
def components?
|
182
|
+
!component_map.empty?
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
|
187
|
+
def register_component(component)
|
188
|
+
Reality::Model::TestCase::MyContainer.error("Attempting to register duplicate component definition with name '\#{name}'") if component_by_name?(component.name)
|
189
|
+
component_map[component.name.to_s] = component
|
190
|
+
end
|
191
|
+
|
192
|
+
def component_map
|
193
|
+
@component_map ||= Reality::OrderedHash.new
|
194
|
+
end
|
195
|
+
CODE
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_build_model_code
|
199
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer)
|
200
|
+
element1 = Reality::Model::ModelElement.new(repository, :bundle, nil, {})
|
201
|
+
|
202
|
+
code = element1.send(:build_model_code)
|
203
|
+
assert_equal code, <<CODE
|
204
|
+
class Bundle
|
205
|
+
attr_reader :name
|
206
|
+
|
207
|
+
def initialize(name, options = {}, &block)
|
208
|
+
@name = name
|
209
|
+
Reality::Model::TestCase::MyContainer.send(:register_bundle, self)
|
210
|
+
Reality::Model::TestCase::MyContainer.info "Bundle '\#{name}' definition started."
|
211
|
+
pre_init if respond_to?(:pre_init, true)
|
212
|
+
self.options = options
|
213
|
+
yield self if block_given?
|
214
|
+
post_init if respond_to?(:post_init, true)
|
215
|
+
Reality::Model::TestCase::MyContainer.info "Bundle '\#{name}' definition completed."
|
216
|
+
end
|
217
|
+
|
218
|
+
public
|
219
|
+
|
220
|
+
def options=(options)
|
221
|
+
options.each_pair do |k, v|
|
222
|
+
keys = k.to_s.split('.')
|
223
|
+
target = self
|
224
|
+
keys[0, keys.length - 1].each do |target_accessor_key|
|
225
|
+
target = target.send target_accessor_key.to_sym
|
226
|
+
end
|
227
|
+
begin
|
228
|
+
target.send "\#{keys.last}=", v
|
229
|
+
rescue NoMethodError
|
230
|
+
raise "Attempted to configure property \\"\#{keys.last}\\" on Bundle but property does not exist."
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
CODE
|
236
|
+
end
|
237
|
+
|
238
|
+
def test_build_model_code_for_contained_model
|
239
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer)
|
240
|
+
Reality::Model::ModelElement.new(repository, :project, nil, {})
|
241
|
+
element1 = Reality::Model::ModelElement.new(repository, :bundle, :project, {})
|
242
|
+
|
243
|
+
code = element1.send(:build_model_code)
|
244
|
+
assert_equal code, <<CODE
|
245
|
+
class Bundle
|
246
|
+
attr_reader :name
|
247
|
+
attr_reader :project
|
248
|
+
|
249
|
+
def initialize(project, name, options = {}, &block)
|
250
|
+
@name = name
|
251
|
+
@project = project
|
252
|
+
@project.send(:register_bundle, self)
|
253
|
+
Reality::Model::TestCase::MyContainer.info "Bundle '\#{name}' definition started."
|
254
|
+
pre_init if respond_to?(:pre_init, true)
|
255
|
+
self.options = options
|
256
|
+
yield self if block_given?
|
257
|
+
post_init if respond_to?(:post_init, true)
|
258
|
+
Reality::Model::TestCase::MyContainer.info "Bundle '\#{name}' definition completed."
|
259
|
+
end
|
260
|
+
|
261
|
+
public
|
262
|
+
|
263
|
+
def options=(options)
|
264
|
+
options.each_pair do |k, v|
|
265
|
+
keys = k.to_s.split('.')
|
266
|
+
target = self
|
267
|
+
keys[0, keys.length - 1].each do |target_accessor_key|
|
268
|
+
target = target.send target_accessor_key.to_sym
|
269
|
+
end
|
270
|
+
begin
|
271
|
+
target.send "\#{keys.last}=", v
|
272
|
+
rescue NoMethodError
|
273
|
+
raise "Attempted to configure property \\"\#{keys.last}\\" on Bundle but property does not exist."
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
CODE
|
279
|
+
end
|
280
|
+
|
281
|
+
def test_build_model_code_with_custom_initializer
|
282
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer)
|
283
|
+
element1 = Reality::Model::ModelElement.new(repository, :bundle, nil, :custom_initialize => true)
|
284
|
+
|
285
|
+
code = element1.send(:build_model_code)
|
286
|
+
assert_equal code, <<CODE
|
287
|
+
class Bundle
|
288
|
+
attr_reader :name
|
289
|
+
|
290
|
+
def perform_init(name, options = {}, &block)
|
291
|
+
@name = name
|
292
|
+
Reality::Model::TestCase::MyContainer.send(:register_bundle, self)
|
293
|
+
Reality::Model::TestCase::MyContainer.info "Bundle '\#{name}' definition started."
|
294
|
+
pre_init if respond_to?(:pre_init, true)
|
295
|
+
self.options = options
|
296
|
+
yield self if block_given?
|
297
|
+
post_init if respond_to?(:post_init, true)
|
298
|
+
Reality::Model::TestCase::MyContainer.info "Bundle '\#{name}' definition completed."
|
299
|
+
end
|
300
|
+
|
301
|
+
public
|
302
|
+
|
303
|
+
def options=(options)
|
304
|
+
options.each_pair do |k, v|
|
305
|
+
keys = k.to_s.split('.')
|
306
|
+
target = self
|
307
|
+
keys[0, keys.length - 1].each do |target_accessor_key|
|
308
|
+
target = target.send target_accessor_key.to_sym
|
309
|
+
end
|
310
|
+
begin
|
311
|
+
target.send "\#{keys.last}=", v
|
312
|
+
rescue NoMethodError
|
313
|
+
raise "Attempted to configure property \\"\#{keys.last}\\" on Bundle but property does not exist."
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
CODE
|
319
|
+
end
|
320
|
+
|
321
|
+
module MyFacetManager
|
322
|
+
end
|
323
|
+
|
324
|
+
def test_build_model_code_that_is_faceted
|
325
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer, :facet_container => MyFacetManager)
|
326
|
+
element1 = Reality::Model::ModelElement.new(repository, :bundle, nil, {})
|
327
|
+
|
328
|
+
code = element1.send(:build_model_code)
|
329
|
+
assert_equal code, <<CODE
|
330
|
+
class Bundle
|
331
|
+
attr_reader :name
|
332
|
+
|
333
|
+
def initialize(name, options = {}, &block)
|
334
|
+
@name = name
|
335
|
+
Reality::Model::TestCase::MyContainer.send(:register_bundle, self)
|
336
|
+
Reality::Model::TestModelElement::MyFacetManager.target_manager.apply_extension(self)
|
337
|
+
Reality::Model::TestCase::MyContainer.info "Bundle '\#{name}' definition started."
|
338
|
+
pre_init if respond_to?(:pre_init, true)
|
339
|
+
self.options = options
|
340
|
+
yield self if block_given?
|
341
|
+
post_init if respond_to?(:post_init, true)
|
342
|
+
Reality::Model::TestCase::MyContainer.info "Bundle '\#{name}' definition completed."
|
343
|
+
end
|
344
|
+
|
345
|
+
public
|
346
|
+
|
347
|
+
def options=(options)
|
348
|
+
options.each_pair do |k, v|
|
349
|
+
keys = k.to_s.split('.')
|
350
|
+
target = self
|
351
|
+
keys[0, keys.length - 1].each do |target_accessor_key|
|
352
|
+
target = target.send target_accessor_key.to_sym
|
353
|
+
end
|
354
|
+
begin
|
355
|
+
target.send "\#{keys.last}=", v
|
356
|
+
rescue NoMethodError
|
357
|
+
raise "Attempted to configure property \\"\#{keys.last}\\" on Bundle but property does not exist."
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
CODE
|
363
|
+
end
|
364
|
+
|
365
|
+
def test_build_model_code_for_containing_model
|
366
|
+
repository = Reality::Model::Repository.new(:MyTypeSystem, MyContainer)
|
367
|
+
element0 = Reality::Model::ModelElement.new(repository, :project, nil, {})
|
368
|
+
Reality::Model::ModelElement.new(repository, :bundle, :project, {})
|
369
|
+
|
370
|
+
code = element0.send(:build_model_code)
|
371
|
+
assert_equal code, <<CODE
|
372
|
+
class Project
|
373
|
+
attr_reader :name
|
374
|
+
|
375
|
+
def initialize(name, options = {}, &block)
|
376
|
+
@name = name
|
377
|
+
Reality::Model::TestCase::MyContainer.send(:register_project, self)
|
378
|
+
Reality::Model::TestCase::MyContainer.info "Project '\#{name}' definition started."
|
379
|
+
pre_init if respond_to?(:pre_init, true)
|
380
|
+
self.options = options
|
381
|
+
yield self if block_given?
|
382
|
+
post_init if respond_to?(:post_init, true)
|
383
|
+
Reality::Model::TestCase::MyContainer.info "Project '\#{name}' definition completed."
|
384
|
+
end
|
385
|
+
|
386
|
+
public
|
387
|
+
|
388
|
+
def bundle(name, options = {}, &block)
|
389
|
+
Reality::Model::TestCase::MyContainer::Bundle.new(self, name, options, &block)
|
390
|
+
end
|
391
|
+
|
392
|
+
def bundle_by_name?(name)
|
393
|
+
!!bundle_map[name.to_s]
|
394
|
+
end
|
395
|
+
|
396
|
+
def bundle_by_name(name)
|
397
|
+
bundle = bundle_map[name.to_s]
|
398
|
+
raise "No bundle with name '\#{name}' defined." unless bundle
|
399
|
+
bundle
|
400
|
+
end
|
401
|
+
|
402
|
+
def bundles
|
403
|
+
bundle_map.values
|
404
|
+
end
|
405
|
+
|
406
|
+
def bundles?
|
407
|
+
!bundle_map.empty?
|
408
|
+
end
|
409
|
+
|
410
|
+
private
|
411
|
+
|
412
|
+
def register_bundle(bundle)
|
413
|
+
Reality::Model::TestCase::MyContainer.error("Attempting to register duplicate bundle definition with name '\#{name}'") if bundle_by_name?(bundle.name)
|
414
|
+
bundle_map[bundle.name.to_s] = bundle
|
415
|
+
end
|
416
|
+
|
417
|
+
def bundle_map
|
418
|
+
@bundle_map ||= Reality::OrderedHash.new
|
419
|
+
end
|
420
|
+
|
421
|
+
public
|
422
|
+
|
423
|
+
def options=(options)
|
424
|
+
options.each_pair do |k, v|
|
425
|
+
keys = k.to_s.split('.')
|
426
|
+
target = self
|
427
|
+
keys[0, keys.length - 1].each do |target_accessor_key|
|
428
|
+
target = target.send target_accessor_key.to_sym
|
429
|
+
end
|
430
|
+
begin
|
431
|
+
target.send "\#{keys.last}=", v
|
432
|
+
rescue NoMethodError
|
433
|
+
raise "Attempted to configure property \\"\#{keys.last}\\" on Project but property does not exist."
|
434
|
+
end
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
CODE
|
439
|
+
end
|
440
|
+
|
441
|
+
module ResgenContainer
|
442
|
+
end
|
443
|
+
|
444
|
+
def test_define_ruby_class
|
445
|
+
repository = Reality::Model::Repository.new(:Resgen, ResgenContainer)
|
446
|
+
model1 = Reality::Model::ModelElement.new(repository, :project, nil, {})
|
447
|
+
model2 = Reality::Model::ModelElement.new(repository, :bundle, :project, {})
|
448
|
+
|
449
|
+
assert_equal false, ResgenContainer.const_defined?(:Project)
|
450
|
+
assert_equal false, ResgenContainer.const_defined?(:Bundle)
|
451
|
+
|
452
|
+
model1.send(:define_ruby_class, ResgenContainer)
|
453
|
+
|
454
|
+
assert_equal true, ResgenContainer.const_defined?(:Project)
|
455
|
+
assert_equal false, ResgenContainer.const_defined?(:Bundle)
|
456
|
+
|
457
|
+
model2.send(:define_ruby_class, ResgenContainer)
|
458
|
+
|
459
|
+
assert_equal true, ResgenContainer.const_defined?(:Project)
|
460
|
+
assert_equal true, ResgenContainer.const_defined?(:Bundle)
|
461
|
+
|
462
|
+
assert_true ResgenContainer::Project.instance_methods.include?(:name)
|
463
|
+
assert_true ResgenContainer::Project.instance_methods.include?(:bundles)
|
464
|
+
assert_true ResgenContainer::Project.instance_methods.include?(:bundle_by_name)
|
465
|
+
assert_true ResgenContainer::Project.instance_methods.include?(:bundle_by_name?)
|
466
|
+
assert_true ResgenContainer::Project.instance_methods.include?(:bundle)
|
467
|
+
assert_false ResgenContainer::Project.instance_methods.include?(:perform_init)
|
468
|
+
|
469
|
+
assert_true ResgenContainer::Bundle.instance_methods.include?(:project)
|
470
|
+
assert_true ResgenContainer::Bundle.instance_methods.include?(:name)
|
471
|
+
assert_false ResgenContainer::Bundle.instance_methods.include?(:perform_init)
|
472
|
+
end
|
473
|
+
|
474
|
+
module ResgenContainer2
|
475
|
+
end
|
476
|
+
|
477
|
+
def test_define_ruby_class_with_heavy_customization
|
478
|
+
repository = Reality::Model::Repository.new(:Resgen, ResgenContainer2)
|
479
|
+
model1 = Reality::Model::ModelElement.new(repository, :project, nil, :custom_initialize => true, :model_classname => :Prj, :inverse_access_method => :prj, :id_method => :key)
|
480
|
+
model2 = Reality::Model::ModelElement.new(repository, :bundle, :project, :custom_initialize => true, :inverse_access_method => :bnd, :access_method => :bnds, :id_method => :key)
|
481
|
+
|
482
|
+
assert_equal false, ResgenContainer2.const_defined?(:Prj)
|
483
|
+
assert_equal false, ResgenContainer2.const_defined?(:Bundle)
|
484
|
+
|
485
|
+
model1.send(:define_ruby_class, ResgenContainer2)
|
486
|
+
|
487
|
+
assert_equal true, ResgenContainer2.const_defined?(:Prj)
|
488
|
+
assert_equal false, ResgenContainer2.const_defined?(:Bundle)
|
489
|
+
|
490
|
+
model2.send(:define_ruby_class, ResgenContainer2)
|
491
|
+
|
492
|
+
assert_equal true, ResgenContainer2.const_defined?(:Prj)
|
493
|
+
assert_equal true, ResgenContainer2.const_defined?(:Bundle)
|
494
|
+
|
495
|
+
assert_equal ResgenContainer2::Prj, model1.model
|
496
|
+
assert_equal ResgenContainer2::Bundle, model2.model
|
497
|
+
|
498
|
+
assert_true ResgenContainer2::Prj.instance_methods.include?(:key)
|
499
|
+
assert_false ResgenContainer2::Prj.instance_methods.include?(:name)
|
500
|
+
assert_true ResgenContainer2::Prj.instance_methods.include?(:bnds)
|
501
|
+
assert_true ResgenContainer2::Prj.instance_methods.include?(:bnd_by_key)
|
502
|
+
assert_true ResgenContainer2::Prj.instance_methods.include?(:bnd_by_key?)
|
503
|
+
|
504
|
+
# Need a custom initializer to be written
|
505
|
+
assert_false ResgenContainer2::Prj.instance_methods.include?(:bundle)
|
506
|
+
assert_false ResgenContainer2::Prj.instance_methods.include?(:bnd)
|
507
|
+
|
508
|
+
assert_true ResgenContainer2::Bundle.instance_methods.include?(:prj)
|
509
|
+
assert_true ResgenContainer2::Bundle.instance_methods.include?(:key)
|
510
|
+
assert_false ResgenContainer2::Bundle.instance_methods.include?(:name)
|
511
|
+
end
|
512
|
+
end
|