vorpal 0.0.7.rc1 → 0.0.7.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -0
- data/README.md +5 -4
- data/lib/vorpal/aggregate_repository.rb +50 -244
- data/lib/vorpal/configuration.rb +5 -5
- data/lib/vorpal/db_driver.rb +44 -3
- data/lib/vorpal/db_loader.rb +7 -1
- data/lib/vorpal/engine.rb +241 -0
- data/lib/vorpal/version.rb +1 -1
- data/lib/vorpal.rb +4 -3
- data/spec/vorpal/acceptance/aggregate_repository_spec.rb +103 -65
- data/spec/vorpal/performance/performance_spec.rb +13 -12
- data/spec/vorpal/unit/config_builder_spec.rb +1 -0
- data/vorpal.gemspec +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b6b4c26a538b1aeac920b566ce3b80e0b04e4fe
|
4
|
+
data.tar.gz: 88d0f3a57930e3a8587d89d085293ac9d032fc58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0190b9231a1ecce12aec8c62a92345e62ae98470f488401f8e0947ddf37bba7573263a9b78b79635958d85614b9249ab952526542cfe48a081c1d6de179ff3d
|
7
|
+
data.tar.gz: 32e2963bc4cb79a56de8499fff09b439475f0371d6b4d6f2cfaa8bb87d5b431070965adfcf708e45546db846063418abcabd5e9e64ed8af4054e9c45fbe37be7
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Please see https://github.com/nulogy/vorpal/releases
|
data/README.md
CHANGED
@@ -109,7 +109,7 @@ require 'vorpal'
|
|
109
109
|
module TreeRepository
|
110
110
|
extend self
|
111
111
|
|
112
|
-
|
112
|
+
engine = Vorpal.define do
|
113
113
|
map Tree do
|
114
114
|
attributes :name
|
115
115
|
belongs_to :gardener, owned: false
|
@@ -123,9 +123,10 @@ module TreeRepository
|
|
123
123
|
belongs_to :tree
|
124
124
|
end
|
125
125
|
end
|
126
|
+
@repository = engine.repository_for(Tree)
|
126
127
|
|
127
|
-
def find(
|
128
|
-
@repository.
|
128
|
+
def find(tree_id)
|
129
|
+
@repository.load_one(@repository.db_class.where(id: tree_id).first)
|
129
130
|
end
|
130
131
|
|
131
132
|
def save(tree)
|
@@ -137,7 +138,7 @@ module TreeRepository
|
|
137
138
|
end
|
138
139
|
|
139
140
|
def destroy_by_id(tree_id)
|
140
|
-
@repository.destroy_by_id(tree_id
|
141
|
+
@repository.destroy_by_id(tree_id)
|
141
142
|
end
|
142
143
|
end
|
143
144
|
```
|
@@ -1,286 +1,92 @@
|
|
1
1
|
require 'vorpal/identity_map'
|
2
|
-
require 'vorpal/aggregate_utils'
|
3
|
-
require 'vorpal/db_loader'
|
4
|
-
require 'vorpal/db_driver'
|
5
2
|
|
6
3
|
module Vorpal
|
7
4
|
class AggregateRepository
|
8
5
|
# @private
|
9
|
-
def initialize(
|
10
|
-
@
|
11
|
-
@
|
6
|
+
def initialize(domain_class, engine)
|
7
|
+
@domain_class = domain_class
|
8
|
+
@engine = engine
|
12
9
|
end
|
13
10
|
|
14
|
-
# Saves
|
11
|
+
# Saves a collection of aggregates to the DB. Inserts objects that are new to an
|
15
12
|
# aggregate, updates existing objects and deletes objects that are no longer
|
16
13
|
# present.
|
17
14
|
#
|
18
|
-
# Objects that are on the boundary of
|
15
|
+
# Objects that are on the boundary of an aggregate (owned: false) will not
|
19
16
|
# be inserted, updated, or deleted. However, the relationships to these
|
20
|
-
# objects (provided they are stored within
|
17
|
+
# objects (provided they are stored within an aggregate) will be saved.
|
21
18
|
#
|
22
|
-
# @param
|
23
|
-
#
|
24
|
-
def persist(root)
|
25
|
-
persist_all([root]).first
|
26
|
-
end
|
27
|
-
|
28
|
-
# Like {#persist} but operates on multiple aggregates. Roots must
|
29
|
-
# be of the same type.
|
30
|
-
#
|
31
|
-
# @param roots [[Object]] array of aggregate roots to be saved.
|
19
|
+
# @param roots [[Object]] array of aggregate roots to be saved. Will also accept a
|
20
|
+
# single aggregate.
|
32
21
|
# @return [[Object]] array of aggregate roots.
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
all_owned_objects = all_owned_objects(roots)
|
38
|
-
mapping = {}
|
39
|
-
loaded_db_objects = load_owned_from_db(roots.map(&:id).compact, roots.first.class)
|
40
|
-
|
41
|
-
serialize(all_owned_objects, mapping, loaded_db_objects)
|
42
|
-
new_objects = get_unsaved_objects(mapping.keys)
|
43
|
-
begin
|
44
|
-
set_primary_keys(all_owned_objects, mapping)
|
45
|
-
set_foreign_keys(all_owned_objects, mapping)
|
46
|
-
remove_orphans(mapping, loaded_db_objects)
|
47
|
-
save(all_owned_objects, new_objects, mapping)
|
48
|
-
|
49
|
-
return roots
|
50
|
-
rescue Exception
|
51
|
-
nil_out_object_ids(new_objects)
|
52
|
-
raise
|
53
|
-
end
|
22
|
+
# @raise [InvalidAggregateRoot] When any of the roots are nil.
|
23
|
+
def persist(roots)
|
24
|
+
@engine.persist(roots)
|
54
25
|
end
|
55
26
|
|
56
27
|
# Loads an aggregate from the DB. Will eagerly load all objects in the
|
57
28
|
# aggregate and on the boundary (owned: false).
|
58
29
|
#
|
59
|
-
# @param
|
60
|
-
# loaded.
|
61
|
-
# @param
|
62
|
-
#
|
63
|
-
# @param identity_map [Vorpal::IdentityMap] Provide your own IdentityMap instance
|
64
|
-
# if you want entity id - unique object mapping for a greater scope than one
|
30
|
+
# @param db_root [Object] DB representation of the root of the aggregate to be
|
31
|
+
# loaded. This can be nil.
|
32
|
+
# @param identity_map [IdentityMap] Provide your own IdentityMap instance
|
33
|
+
# if you want entity id -> unique object mapping for a greater scope than one
|
65
34
|
# operation.
|
66
|
-
# @return [Object]
|
67
|
-
def
|
68
|
-
|
35
|
+
# @return [Object] Aggregate root corresponding to the given DB representation.
|
36
|
+
def load_one(db_root, identity_map=IdentityMap.new)
|
37
|
+
@engine.load_one(db_root, @domain_class, identity_map)
|
69
38
|
end
|
70
39
|
|
71
|
-
# Like {#
|
40
|
+
# Like {#load_one} but operates on multiple aggregate roots.
|
72
41
|
#
|
73
|
-
# @param
|
42
|
+
# @param db_roots [[Integer]] Array of primary key values of the roots of the
|
74
43
|
# aggregates to be loaded.
|
75
|
-
# @param
|
76
|
-
#
|
77
|
-
# if you want entity id - unique object mapping for a greater scope than one
|
44
|
+
# @param identity_map [IdentityMap] Provide your own IdentityMap instance
|
45
|
+
# if you want entity id -> unique object mapping for a greater scope than one
|
78
46
|
# operation.
|
79
|
-
# @return [[Object]]
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
loaded_db_objects = load_from_db(ids, domain_class)
|
84
|
-
objects = deserialize(loaded_db_objects, identity_map)
|
85
|
-
set_associations(loaded_db_objects, identity_map)
|
86
|
-
|
87
|
-
sorted_roots(ids, objects, domain_class)
|
88
|
-
end
|
89
|
-
|
90
|
-
# Removes an aggregate from the DB. Even if the aggregate contains unsaved
|
91
|
-
# changes this method will correctly remove everything.
|
92
|
-
#
|
93
|
-
# @param root [Object] Root of the aggregate to be destroyed.
|
94
|
-
# @return [Object] Root that was passed in.
|
95
|
-
def destroy(root)
|
96
|
-
destroy_all([root]).first
|
47
|
+
# @return [[Object]] Aggregate roots corresponding to the given DB representations.
|
48
|
+
# @raise [InvalidAggregateRoot] When any of the db_roots are nil.
|
49
|
+
def load_many(db_roots, identity_map=IdentityMap.new)
|
50
|
+
@engine.load_many(db_roots, @domain_class, identity_map)
|
97
51
|
end
|
98
52
|
|
99
|
-
#
|
100
|
-
#
|
53
|
+
# Removes a collection of aggregates from the DB. Even if an aggregate
|
54
|
+
# contains unsaved changes this method will correctly remove everything.
|
101
55
|
#
|
102
|
-
# @param roots [[Object]]
|
56
|
+
# @param roots [[Object]] Roots of the aggregates to be destroyed. Also accepts a
|
57
|
+
# single root.
|
103
58
|
# @return [[Object]] Roots that were passed in.
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
destroy_all_by_id(roots.map(&:id), roots.first.class)
|
109
|
-
roots
|
59
|
+
# @raise [InvalidAggregateRoot] When any of the roots are nil.
|
60
|
+
def destroy(roots)
|
61
|
+
@engine.destroy(roots)
|
110
62
|
end
|
111
63
|
|
112
|
-
# Removes
|
64
|
+
# Removes a collection of aggregates from the DB given their primary keys.
|
113
65
|
#
|
114
|
-
# @param
|
115
|
-
#
|
116
|
-
#
|
117
|
-
def destroy_by_id(
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
# Like {#destroy_by_id} but operates on multiple ids. Roots must
|
122
|
-
# be of the same type.
|
123
|
-
#
|
124
|
-
# @param ids [[Integer]] Ids of roots of the aggregates to be destroyed.
|
125
|
-
# @param domain_class [Class] Type of the roots of the aggregates to
|
126
|
-
# be destroyed.
|
127
|
-
def destroy_all_by_id(ids, domain_class)
|
128
|
-
raise InvalidPrimaryKeyValue, 'Nil primary key values are not allowed.' if ids.any?(&:nil?)
|
129
|
-
|
130
|
-
loaded_db_objects = load_owned_from_db(ids, domain_class)
|
131
|
-
loaded_db_objects.each do |config, db_objects|
|
132
|
-
@db_driver.destroy(config, db_objects.map(&:id))
|
133
|
-
end
|
134
|
-
ids
|
66
|
+
# @param ids [[Integer]] Ids of roots of the aggregates to be destroyed. Also
|
67
|
+
# accepts a single id.
|
68
|
+
# @raise [InvalidPrimaryKeyValue] When any of the ids are nil.
|
69
|
+
def destroy_by_id(ids)
|
70
|
+
@engine.destroy_by_id(ids, @domain_class)
|
135
71
|
end
|
136
72
|
|
137
73
|
# Returns the DB Class (e.g. ActiveRecord::Base class) that is responsible
|
138
74
|
# for accessing the associated data in the DB.
|
139
|
-
def db_class
|
140
|
-
@
|
141
|
-
end
|
142
|
-
|
143
|
-
private
|
144
|
-
|
145
|
-
def all_owned_objects(roots)
|
146
|
-
AggregateUtils.group_by_type(roots, @configs)
|
147
|
-
end
|
148
|
-
|
149
|
-
def load_from_db(ids, domain_class, only_owned=false)
|
150
|
-
DbLoader.new(only_owned, @db_driver).load_from_db(ids, @configs.config_for(domain_class))
|
151
|
-
end
|
152
|
-
|
153
|
-
def load_owned_from_db(ids, domain_class)
|
154
|
-
load_from_db(ids, domain_class, true)
|
155
|
-
end
|
156
|
-
|
157
|
-
def deserialize(loaded_db_objects, identity_map)
|
158
|
-
loaded_db_objects.flat_map do |config, db_objects|
|
159
|
-
db_objects.map do |db_object|
|
160
|
-
# TODO: There is a bug here when you have something in the IdentityMap that is stale and needs to be updated.
|
161
|
-
identity_map.get_and_set(db_object) { config.deserialize(db_object) }
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def set_associations(loaded_db_objects, identity_map)
|
167
|
-
loaded_db_objects.each do |config, db_objects|
|
168
|
-
db_objects.each do |db_object|
|
169
|
-
config.local_association_configs.each do |association_config|
|
170
|
-
db_remote = loaded_db_objects.find_by_id(
|
171
|
-
association_config.remote_class_config(db_object),
|
172
|
-
association_config.fk_value(db_object)
|
173
|
-
)
|
174
|
-
association_config.associate(identity_map.get(db_object), identity_map.get(db_remote))
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def sorted_roots(ids, objects, domain_class)
|
181
|
-
roots = objects.select { |obj| obj.class == domain_class }
|
182
|
-
roots_by_id = roots.reduce({}) { |h, root| h[root.id] = root; h }
|
183
|
-
ids.map { |id| roots_by_id[id] }.compact
|
184
|
-
end
|
185
|
-
|
186
|
-
def serialize(owned_objects, mapping, loaded_db_objects)
|
187
|
-
owned_objects.each do |config, objects|
|
188
|
-
objects.each do |object|
|
189
|
-
db_object = serialize_object(object, config, loaded_db_objects)
|
190
|
-
mapping[object] = db_object
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def serialize_object(object, config, loaded_db_objects)
|
196
|
-
if config.serialization_required?
|
197
|
-
attributes = config.serialize(object)
|
198
|
-
if object.id.nil?
|
199
|
-
config.build_db_object(attributes)
|
200
|
-
else
|
201
|
-
db_object = loaded_db_objects.find_by_id(config, object.id)
|
202
|
-
config.set_db_object_attributes(db_object, attributes)
|
203
|
-
db_object
|
204
|
-
end
|
205
|
-
else
|
206
|
-
object
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
def set_primary_keys(owned_objects, mapping)
|
211
|
-
owned_objects.each do |config, objects|
|
212
|
-
in_need_of_primary_keys = objects.find_all { |obj| obj.id.nil? }
|
213
|
-
primary_keys = @db_driver.get_primary_keys(config, in_need_of_primary_keys.length)
|
214
|
-
in_need_of_primary_keys.zip(primary_keys).each do |object, primary_key|
|
215
|
-
mapping[object].id = primary_key
|
216
|
-
object.id = primary_key
|
217
|
-
end
|
218
|
-
end
|
219
|
-
mapping.rehash # needs to happen because setting the id on an AR::Base model changes its hash value
|
220
|
-
end
|
221
|
-
|
222
|
-
def set_foreign_keys(owned_objects, mapping)
|
223
|
-
owned_objects.each do |config, objects|
|
224
|
-
objects.each do |object|
|
225
|
-
config.has_manys.each do |has_many_config|
|
226
|
-
if has_many_config.owned
|
227
|
-
children = has_many_config.get_children(object)
|
228
|
-
children.each do |child|
|
229
|
-
has_many_config.set_foreign_key(mapping[child], object)
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
config.has_ones.each do |has_one_config|
|
235
|
-
if has_one_config.owned
|
236
|
-
child = has_one_config.get_child(object)
|
237
|
-
has_one_config.set_foreign_key(mapping[child], object)
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
config.belongs_tos.each do |belongs_to_config|
|
242
|
-
child = belongs_to_config.get_child(object)
|
243
|
-
belongs_to_config.set_foreign_key(mapping[object], child)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
def save(owned_objects, new_objects, mapping)
|
250
|
-
grouped_new_objects = new_objects.group_by { |obj| @configs.config_for(obj.class) }
|
251
|
-
owned_objects.each do |config, objects|
|
252
|
-
objects_to_insert = grouped_new_objects[config] || []
|
253
|
-
db_objects_to_insert = objects_to_insert.map { |obj| mapping[obj] }
|
254
|
-
@db_driver.insert(config, db_objects_to_insert)
|
255
|
-
|
256
|
-
objects_to_update = objects - objects_to_insert
|
257
|
-
db_objects_to_update = objects_to_update.map { |obj| mapping[obj] }
|
258
|
-
@db_driver.update(config, db_objects_to_update)
|
259
|
-
end
|
75
|
+
def db_class
|
76
|
+
@engine.db_class(@domain_class)
|
260
77
|
end
|
261
78
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
@db_driver.destroy(config, orphans)
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
def get_unsaved_objects(objects)
|
273
|
-
objects.find_all { |object| object.id.nil? }
|
79
|
+
# Access to the underlying mapping {Engine}. Provided in case access to another aggregate
|
80
|
+
# or another db_class is required.
|
81
|
+
#
|
82
|
+
# @return [Engine] Mapping interface not specific to a particular aggregate root.
|
83
|
+
def engine
|
84
|
+
@engine
|
274
85
|
end
|
275
86
|
|
276
|
-
def
|
277
|
-
|
278
|
-
|
87
|
+
def query
|
88
|
+
# db_class.unscoped.extending(ArelQueryMethods.new(self))
|
89
|
+
@engine.query(@domain_class)
|
279
90
|
end
|
280
91
|
end
|
281
|
-
|
282
|
-
class InvalidPrimaryKeyValue < StandardError
|
283
|
-
end
|
284
|
-
class InvalidAggregateRoot < StandardError
|
285
|
-
end
|
286
92
|
end
|
data/lib/vorpal/configuration.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
require 'vorpal/
|
1
|
+
require 'vorpal/engine'
|
2
2
|
require 'vorpal/config_builder'
|
3
3
|
|
4
4
|
module Vorpal
|
5
5
|
module Configuration
|
6
6
|
|
7
|
-
# Configures and creates a {
|
7
|
+
# Configures and creates a {Engine} instance.
|
8
8
|
#
|
9
9
|
# @param options [Hash] Global configuration options for the repository instance.
|
10
10
|
# @option options [Object] :db_driver (Object that will be used to interact with the DB.)
|
11
|
-
# Must be duck-type compatible with {
|
11
|
+
# Must be duck-type compatible with {DbDriver}.
|
12
12
|
#
|
13
|
-
# @return [
|
13
|
+
# @return [Engine] Instance of the mapping engine.
|
14
14
|
def define(options={}, &block)
|
15
15
|
master_config = build_config(&block)
|
16
16
|
db_driver = options.fetch(:db_driver, DbDriver.new)
|
17
|
-
|
17
|
+
Engine.new(db_driver, master_config)
|
18
18
|
end
|
19
19
|
|
20
20
|
# Maps a domain class to a relational table.
|
data/lib/vorpal/db_driver.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Vorpal
|
2
|
-
#
|
2
|
+
# Interface between the database and Vorpal
|
3
3
|
#
|
4
|
-
# Currently only works for PostgreSQL.
|
4
|
+
# Currently only works for PostgreSQL via ActiveRecord.
|
5
5
|
class DbDriver
|
6
6
|
def initialize
|
7
7
|
@sequence_names = {}
|
@@ -29,13 +29,16 @@ module Vorpal
|
|
29
29
|
|
30
30
|
# Loads instances of the given class by primary key.
|
31
31
|
#
|
32
|
+
# @param class_config [ClassConfig]
|
32
33
|
# @return [[Object]] An array of entities.
|
33
34
|
def load_by_id(class_config, ids)
|
34
|
-
class_config.db_class.where(id: ids)
|
35
|
+
class_config.db_class.where(id: ids).all
|
35
36
|
end
|
36
37
|
|
37
38
|
# Loads instances of the given class whose foreign key has the given value.
|
38
39
|
#
|
40
|
+
# @param class_config [ClassConfig]
|
41
|
+
# @param foreign_key_info [ForeignKeyInfo]
|
39
42
|
# @return [[Object]] An array of entities.
|
40
43
|
def load_by_foreign_key(class_config, id, foreign_key_info)
|
41
44
|
arel = class_config.db_class.where(foreign_key_info.fk_column => id)
|
@@ -45,6 +48,7 @@ module Vorpal
|
|
45
48
|
|
46
49
|
# Fetches primary key values to be used for new entities.
|
47
50
|
#
|
51
|
+
# @param class_config [ClassConfig] Config of the entity whose primary keys are being fetched.
|
48
52
|
# @return [[Integer]] An array of unused primary keys.
|
49
53
|
def get_primary_keys(class_config, count)
|
50
54
|
result = execute("select nextval($1) from generate_series(1,$2);", [sequence_name(class_config), count])
|
@@ -53,6 +57,7 @@ module Vorpal
|
|
53
57
|
|
54
58
|
# Builds an ORM Class for accessing data in the given DB table.
|
55
59
|
#
|
60
|
+
# @param table_name [String] Name of the DB table the DB class should interface with.
|
56
61
|
# @return [Class] ActiveRecord::Base Class
|
57
62
|
def build_db_class(table_name)
|
58
63
|
db_class = Class.new(ActiveRecord::Base)
|
@@ -60,6 +65,13 @@ module Vorpal
|
|
60
65
|
db_class
|
61
66
|
end
|
62
67
|
|
68
|
+
# Builds a composable query object (e.g. ActiveRecord::Relation) with Vorpal methods mixed in.
|
69
|
+
#
|
70
|
+
# @param class_config [ClassConfig] Config of the entity whose db representations should be returned.
|
71
|
+
def query(class_config)
|
72
|
+
class_config.db_class.unscoped.extending(ArelQueryMethods.new(self))
|
73
|
+
end
|
74
|
+
|
63
75
|
private
|
64
76
|
|
65
77
|
def sequence_name(class_config)
|
@@ -74,4 +86,33 @@ module Vorpal
|
|
74
86
|
ActiveRecord::Base.connection.exec_query(sql, 'SQL', binds)
|
75
87
|
end
|
76
88
|
end
|
89
|
+
|
90
|
+
class ArelQueryMethods < Module
|
91
|
+
def initialize(repository)
|
92
|
+
@repository = repository
|
93
|
+
end
|
94
|
+
|
95
|
+
def extended(descendant)
|
96
|
+
super
|
97
|
+
descendant.extend(Methods)
|
98
|
+
descendant.vorpal_aggregate_repository = @repository
|
99
|
+
end
|
100
|
+
|
101
|
+
# Methods in this module will appear on any composable
|
102
|
+
module Methods
|
103
|
+
attr_writer :vorpal_aggregate_repository
|
104
|
+
|
105
|
+
# See {AggregateRepository#load_many}.
|
106
|
+
def load_many
|
107
|
+
db_roots = self.all
|
108
|
+
@vorpal_aggregate_repository.load_many(db_roots)
|
109
|
+
end
|
110
|
+
|
111
|
+
# See {AggregateRepository#load_one}.
|
112
|
+
def load_one
|
113
|
+
db_root = self.first
|
114
|
+
@vorpal_aggregate_repository.load_one(db_root)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
77
118
|
end
|
data/lib/vorpal/db_loader.rb
CHANGED
@@ -13,9 +13,15 @@ module Vorpal
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def load_from_db(ids, config)
|
16
|
+
db_roots = @db_driver.load_by_id(config, ids)
|
17
|
+
load_from_db_objects(db_roots, config)
|
18
|
+
end
|
19
|
+
|
20
|
+
def load_from_db_objects(db_roots, config)
|
16
21
|
@loaded_objects = LoadedObjects.new
|
22
|
+
@loaded_objects.add(config, db_roots)
|
17
23
|
@lookup_instructions = LookupInstructions.new
|
18
|
-
|
24
|
+
explore_objects(config, db_roots)
|
19
25
|
|
20
26
|
until @lookup_instructions.empty?
|
21
27
|
lookup = @lookup_instructions.next_lookup
|