vorpal 0.0.6.rc4 → 0.0.6
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 +8 -8
- data/README.md +10 -3
- data/lib/vorpal/aggregate_repository.rb +227 -190
- data/lib/vorpal/aggregate_traversal.rb +35 -35
- data/lib/vorpal/aggregate_utils.rb +1 -0
- data/lib/vorpal/config_builder.rb +120 -119
- data/lib/vorpal/configs.rb +22 -8
- data/lib/vorpal/configuration.rb +43 -40
- data/lib/vorpal/db_driver.rb +14 -2
- data/lib/vorpal/db_loader.rb +102 -104
- data/lib/vorpal/identity_map.rb +25 -25
- data/lib/vorpal/loaded_objects.rb +29 -28
- data/lib/vorpal/util/array_hash.rb +12 -14
- data/lib/vorpal/version.rb +1 -1
- data/spec/vorpal/{aggregate_repository_spec.rb → acceptance/aggregate_repository_spec.rb} +133 -2
- data/spec/vorpal/{performance_spec.rb → acceptance/performance_spec.rb} +4 -4
- data/spec/vorpal/{class_config_builder_spec.rb → unit/class_config_builder_spec.rb} +0 -0
- data/spec/vorpal/{configs_spec.rb → unit/configs_spec.rb} +0 -0
- data/spec/vorpal/{identity_map_spec.rb → unit/identity_map_spec.rb} +0 -0
- data/spec/vorpal/unit/loaded_objects_spec.rb +22 -0
- data/vorpal.gemspec +1 -0
- metadata +30 -14
@@ -1,50 +1,50 @@
|
|
1
1
|
module Vorpal
|
2
|
-
# @private
|
3
|
-
class AggregateTraversal
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
# @private
|
3
|
+
class AggregateTraversal
|
4
|
+
def initialize(configs)
|
5
|
+
@configs = configs
|
6
|
+
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
# Traversal should always begin with an object that is known to be
|
9
|
+
# able to reach all other objects in the aggregate (like the root!)
|
10
|
+
def accept(object, visitor, already_visited=[])
|
11
|
+
return if object.nil?
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
config = @configs.config_for(object.class)
|
14
|
+
return if config.nil?
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
return if already_visited.include?(object)
|
17
|
+
already_visited << object
|
18
18
|
|
19
|
-
|
19
|
+
visitor.visit_object(object, config)
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
config.belongs_tos.each do |belongs_to_config|
|
22
|
+
child = belongs_to_config.get_child(object)
|
23
|
+
accept(child, visitor, already_visited) if visitor.continue_traversal?(belongs_to_config)
|
24
|
+
end
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
config.has_ones.each do |has_one_config|
|
27
|
+
child = has_one_config.get_child(object)
|
28
|
+
accept(child, visitor, already_visited) if visitor.continue_traversal?(has_one_config)
|
29
|
+
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
config.has_manys.each do |has_many_config|
|
32
|
+
children = has_many_config.get_children(object)
|
33
|
+
children.each do |child|
|
34
|
+
accept(child, visitor, already_visited) if visitor.continue_traversal?(has_many_config)
|
35
|
+
end
|
35
36
|
end
|
36
37
|
end
|
37
38
|
end
|
38
|
-
end
|
39
39
|
|
40
|
-
# @private
|
41
|
-
module AggregateVisitorTemplate
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
# @private
|
41
|
+
module AggregateVisitorTemplate
|
42
|
+
def visit_object(object, config)
|
43
|
+
# override me!
|
44
|
+
end
|
45
45
|
|
46
|
-
|
47
|
-
|
46
|
+
def continue_traversal?(association_config)
|
47
|
+
true
|
48
|
+
end
|
48
49
|
end
|
49
|
-
end
|
50
50
|
end
|
@@ -1,148 +1,149 @@
|
|
1
1
|
require 'simple_serializer/serializer'
|
2
2
|
require 'simple_serializer/deserializer'
|
3
3
|
require 'vorpal/configs'
|
4
|
+
require 'active_support/inflector/methods'
|
4
5
|
|
5
6
|
module Vorpal
|
6
|
-
class ConfigBuilder
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
class ConfigBuilder
|
8
|
+
|
9
|
+
# @private
|
10
|
+
def initialize(clazz, options)
|
11
|
+
@domain_class = clazz
|
12
|
+
@class_options = options
|
13
|
+
@has_manys = []
|
14
|
+
@has_ones = []
|
15
|
+
@belongs_tos = []
|
16
|
+
@fields = []
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
# Maps the given fields to and from the domain object and the DB. Not needed
|
20
|
+
# if a serializer and deserializer were provided.
|
21
|
+
def fields(*fields)
|
22
|
+
@fields = fields
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
25
|
+
# Defines a one-to-many association with a list of objects of the same type.
|
26
|
+
#
|
27
|
+
# @param name [String] Name of the field that will refer to the other object.
|
28
|
+
# @param options [Hash]
|
29
|
+
# @option options [Boolean] :owned
|
30
|
+
# @option options [String] :fk
|
31
|
+
# @option options [String] :fk_type
|
32
|
+
# @option options [Class] :child_class
|
33
|
+
def has_many(name, options={})
|
34
|
+
@has_manys << {name: name}.merge(options)
|
35
|
+
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
37
|
+
# Defines a one-to-one association with another object where the foreign key
|
38
|
+
# is stored on the other object.
|
39
|
+
#
|
40
|
+
# @param name [String] Name of the field that will refer to the other object.
|
41
|
+
# @param options [Hash]
|
42
|
+
# @option options [Boolean] :owned
|
43
|
+
# @option options [String] :fk
|
44
|
+
# @option options [String] :fk_type
|
45
|
+
# @option options [Class] :child_class
|
46
|
+
def has_one(name, options={})
|
47
|
+
@has_ones << {name: name}.merge(options)
|
48
|
+
end
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
50
|
+
# Defines a one-to-one association with another object where the foreign key
|
51
|
+
# is stored on this object.
|
52
|
+
#
|
53
|
+
# This association can be polymorphic. i.e.
|
54
|
+
#
|
55
|
+
# @param name [String] Name of the field that will refer to the other object.
|
56
|
+
# @param options [Hash]
|
57
|
+
# @option options [Boolean] :owned
|
58
|
+
# @option options [String] :fk
|
59
|
+
# @option options [String] :fk_type
|
60
|
+
# @option options [Class] :child_class
|
61
|
+
# @option options [[Class]] :child_classes
|
62
|
+
def belongs_to(name, options={})
|
63
|
+
@belongs_tos << {name: name}.merge(options)
|
64
|
+
end
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
66
|
+
# @private
|
67
|
+
def build
|
68
|
+
class_config = build_class_config
|
69
|
+
class_config.has_manys = build_has_manys
|
70
|
+
class_config.has_ones = build_has_ones
|
71
|
+
class_config.belongs_tos = build_belongs_tos
|
71
72
|
|
72
|
-
|
73
|
-
|
73
|
+
class_config
|
74
|
+
end
|
74
75
|
|
75
|
-
|
76
|
+
private
|
76
77
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
78
|
+
def build_class_config
|
79
|
+
Vorpal::ClassConfig.new(
|
80
|
+
domain_class: @domain_class,
|
81
|
+
db_class: @class_options[:to] || db_class,
|
82
|
+
serializer: @class_options[:serializer] || serializer(fields_with_id),
|
83
|
+
deserializer: @class_options[:deserializer] || deserializer(fields_with_id),
|
84
|
+
)
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
87
|
+
def db_class
|
88
|
+
ActiveSupport::Inflector.constantize("#{@domain_class.name}DB")
|
89
|
+
end
|
89
90
|
|
90
|
-
|
91
|
-
|
92
|
-
|
91
|
+
def fields_with_id
|
92
|
+
[:id].concat @fields
|
93
|
+
end
|
93
94
|
|
94
|
-
|
95
|
-
|
96
|
-
|
95
|
+
def build_has_manys
|
96
|
+
@has_manys.map { |options| build_has_many(options) }
|
97
|
+
end
|
97
98
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
99
|
+
def build_has_many(options)
|
100
|
+
options[:child_class] ||= child_class(options[:name])
|
101
|
+
options[:fk] ||= foreign_key(@domain_class.name)
|
102
|
+
options[:owned] = options.fetch(:owned, true)
|
103
|
+
Vorpal::HasManyConfig.new(options)
|
104
|
+
end
|
104
105
|
|
105
|
-
|
106
|
-
|
107
|
-
|
106
|
+
def foreign_key(name)
|
107
|
+
ActiveSupport::Inflector.underscore(name.to_s) + '_id'
|
108
|
+
end
|
108
109
|
|
109
|
-
|
110
|
-
|
111
|
-
|
110
|
+
def child_class(association_name)
|
111
|
+
ActiveSupport::Inflector.constantize(ActiveSupport::Inflector.classify(association_name.to_s))
|
112
|
+
end
|
112
113
|
|
113
|
-
|
114
|
-
|
115
|
-
|
114
|
+
def build_has_ones
|
115
|
+
@has_ones.map { |options| build_has_one(options) }
|
116
|
+
end
|
116
117
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
118
|
+
def build_has_one(options)
|
119
|
+
options[:child_class] ||= child_class(options[:name])
|
120
|
+
options[:fk] ||= foreign_key(@domain_class.name)
|
121
|
+
options[:owned] = options.fetch(:owned, true)
|
122
|
+
Vorpal::HasOneConfig.new(options)
|
123
|
+
end
|
123
124
|
|
124
|
-
|
125
|
-
|
126
|
-
|
125
|
+
def build_belongs_tos
|
126
|
+
@belongs_tos.map { |options| build_belongs_to(options) }
|
127
|
+
end
|
127
128
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
129
|
+
def build_belongs_to(options)
|
130
|
+
child_class = options[:child_classes] || options[:child_class] || child_class(options[:name])
|
131
|
+
options[:child_classes] = Array(child_class)
|
132
|
+
options[:fk] ||= foreign_key(options[:name])
|
133
|
+
options[:owned] = options.fetch(:owned, true)
|
134
|
+
Vorpal::BelongsToConfig.new(options)
|
135
|
+
end
|
135
136
|
|
136
|
-
|
137
|
-
|
138
|
-
|
137
|
+
def serializer(attrs)
|
138
|
+
Class.new(SimpleSerializer::Serializer) do
|
139
|
+
hash_attributes *attrs
|
140
|
+
end
|
139
141
|
end
|
140
|
-
end
|
141
142
|
|
142
|
-
|
143
|
-
|
144
|
-
|
143
|
+
def deserializer(attrs)
|
144
|
+
Class.new(SimpleSerializer::Deserializer) do
|
145
|
+
object_attributes *attrs
|
146
|
+
end
|
145
147
|
end
|
146
148
|
end
|
147
149
|
end
|
148
|
-
end
|
data/lib/vorpal/configs.rb
CHANGED
@@ -149,11 +149,11 @@ module Vorpal
|
|
149
149
|
end
|
150
150
|
|
151
151
|
def get_db_object_attributes(db_object)
|
152
|
-
db_object.attributes
|
152
|
+
symbolize_keys(db_object.attributes)
|
153
153
|
end
|
154
154
|
|
155
155
|
def serialization_required?
|
156
|
-
|
156
|
+
domain_class.superclass.name != 'ActiveRecord::Base'
|
157
157
|
end
|
158
158
|
|
159
159
|
def serialize(object)
|
@@ -172,6 +172,16 @@ module Vorpal
|
|
172
172
|
def get_field(db_object, field)
|
173
173
|
db_object.send(field)
|
174
174
|
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def symbolize_keys(hash)
|
179
|
+
result = {}
|
180
|
+
hash.each_key do |key|
|
181
|
+
result[key.to_sym] = hash[key]
|
182
|
+
end
|
183
|
+
result
|
184
|
+
end
|
175
185
|
end
|
176
186
|
|
177
187
|
# @private
|
@@ -192,6 +202,7 @@ module Vorpal
|
|
192
202
|
end
|
193
203
|
end
|
194
204
|
|
205
|
+
# @private
|
195
206
|
module RemoteEndConfig
|
196
207
|
def child_config
|
197
208
|
association_config.local_class_config
|
@@ -210,6 +221,7 @@ module Vorpal
|
|
210
221
|
end
|
211
222
|
end
|
212
223
|
|
224
|
+
# @private
|
213
225
|
module LocalEndConfig
|
214
226
|
def child_config(db_parent)
|
215
227
|
association_config.remote_class_config(db_parent)
|
@@ -224,6 +236,7 @@ module Vorpal
|
|
224
236
|
end
|
225
237
|
end
|
226
238
|
|
239
|
+
# @private
|
227
240
|
module ToOneConfig
|
228
241
|
def get_child(parent)
|
229
242
|
parent.send(name)
|
@@ -234,6 +247,7 @@ module Vorpal
|
|
234
247
|
end
|
235
248
|
end
|
236
249
|
|
250
|
+
# @private
|
237
251
|
module ToManyConfig
|
238
252
|
def get_children(parent)
|
239
253
|
parent.send(name)
|
@@ -258,22 +272,22 @@ module Vorpal
|
|
258
272
|
end
|
259
273
|
|
260
274
|
# @private
|
261
|
-
class
|
275
|
+
class HasOneConfig
|
262
276
|
include HashInitialization
|
263
|
-
include
|
277
|
+
include RemoteEndConfig
|
264
278
|
include ToOneConfig
|
265
279
|
|
266
|
-
attr_reader :name, :owned, :fk, :fk_type, :
|
280
|
+
attr_reader :name, :owned, :fk, :fk_type, :child_class
|
267
281
|
attr_accessor :association_config
|
268
282
|
end
|
269
283
|
|
270
284
|
# @private
|
271
|
-
class
|
285
|
+
class BelongsToConfig
|
272
286
|
include HashInitialization
|
273
|
-
include
|
287
|
+
include LocalEndConfig
|
274
288
|
include ToOneConfig
|
275
289
|
|
276
|
-
attr_reader :name, :owned, :fk, :fk_type, :
|
290
|
+
attr_reader :name, :owned, :fk, :fk_type, :child_classes
|
277
291
|
attr_accessor :association_config
|
278
292
|
end
|
279
293
|
end
|