vorpal 0.0.7 → 0.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 813b5c4649667d1289ba85df9114c3badab734ed
4
- data.tar.gz: e1e1deb869ccc9b6577b87f9122c056ff0803d62
3
+ metadata.gz: 17ab11df546bfd8e01294e22adea87aca049266c
4
+ data.tar.gz: 1e25a0a08f20f54b277c05e2e90b8bc0d825e85e
5
5
  SHA512:
6
- metadata.gz: 9b7692c298e0f63b8bf1723d2846899e8ac62adc9434e1f01c234e2c027c579752e2bf8d2e95d58c93df9a6d28243b4c9a00f694222608ea825dc3cdad08d7ef
7
- data.tar.gz: 5e5a6b4280a7a94e8f1c1cc0564fb1718af715e3390819caa477f3a99db3f401e15255d37f6f0dfaae48b49eb037a753a4271442e01bcb9c7a5233cef4c5c7f5
6
+ metadata.gz: 5c6f183685c1b5fbd7a89926556a545a20ef87aa604184d5a90223f234780a5a63dd0d69a7e72c864b7dfe79c1fad917f51cb0a8785496400e28d481d7356a27
7
+ data.tar.gz: 70c6768539ac3214339352902e752ae3178eb109d6cb1f791f62719ba18473cc65a7d950435dac40e936e854d4c06b6a4e1050a95edbe39aa7c190810ad2eb89
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/README.md CHANGED
@@ -237,8 +237,8 @@ For example:
237
237
 
238
238
  1. Start a PostgreSQL server.
239
239
  2. Either:
240
- * Create a DB user called `vorpal` with password `pass` and a DB called `vorpal_test`. OR:
241
- * Modify `spec/integration_spec_helper.rb`.
240
+ * Create a DB user called `vorpal` with password `pass`. OR:
241
+ * Modify `spec/helpers/db_helpers.rb`.
242
242
  3. Run `rake` from the terminal.
243
243
 
244
244
  ## Contributors
@@ -87,21 +87,13 @@ module Vorpal
87
87
 
88
88
  # @private
89
89
  def build_db_class
90
- # Module#parent comes from 'active_support/core_ext/module/introspection'
91
- parent_module = @domain_class.parent
92
-
93
- return parent_module.const_get(db_class_name) if parent_module.const_defined?(db_class_name)
94
-
95
- db_class = @db_driver.build_db_class(table_name)
96
- parent_module.const_set(db_class_name, db_class)
97
-
98
- db_class
90
+ @db_driver.build_db_class(table_name)
99
91
  end
100
92
 
101
93
  private
102
94
 
103
95
  def db_class_name
104
- @domain_class.name.split('::').last + 'DB'
96
+ ActiveSupport::Inflector.demodulize(@domain_class.name) + 'DB'
105
97
  end
106
98
 
107
99
  def build_class_config
@@ -125,11 +117,13 @@ module Vorpal
125
117
  end
126
118
 
127
119
  def foreign_key(name)
128
- ActiveSupport::Inflector.underscore(name.to_s) + '_id'
120
+ ActiveSupport::Inflector.foreign_key(name.to_s)
129
121
  end
130
122
 
131
123
  def child_class(association_name)
132
- ActiveSupport::Inflector.constantize(ActiveSupport::Inflector.classify(association_name.to_s))
124
+ # Module#parent comes from 'active_support/core_ext/module/introspection'
125
+ parent_module = @domain_class.parent
126
+ parent_module.const_get(ActiveSupport::Inflector.classify(association_name.to_s))
133
127
  end
134
128
 
135
129
  def build_has_ones
@@ -21,8 +21,9 @@ module Vorpal
21
21
  #
22
22
  # @param domain_class [Class] Type of the domain model to be mapped
23
23
  # @param options [Hash] Configure how to map the domain model
24
- # @option options [String] :to (Class with the same name as the domain class with a 'DB' appended.)
24
+ # @option options [String] :to
25
25
  # Class of the ActiveRecord object that will map this domain class to the DB.
26
+ # Optional, if one is not specified, it will be generated.
26
27
  # @option options [Object] :serializer (map the {ConfigBuilder#attributes} directly)
27
28
  # Object that will convert the domain objects into a hash.
28
29
  #
@@ -60,7 +60,24 @@ module Vorpal
60
60
  # @param table_name [String] Name of the DB table the DB class should interface with.
61
61
  # @return [Class] ActiveRecord::Base Class
62
62
  def build_db_class(table_name)
63
- db_class = Class.new(ActiveRecord::Base)
63
+ db_class = Class.new(ActiveRecord::Base) do
64
+ # This is overridden for two reasons:
65
+ # 1) For anonymous classes, #name normally returns nil. Class names in Ruby come from the
66
+ # name of the constant they are assigned to.
67
+ # 2) Because the default implementation for Class#name for anonymous classes is very, very
68
+ # slow. https://bugs.ruby-lang.org/issues/11119
69
+ # Remove this override once #2 has been fixed!
70
+ def self.name
71
+ @name ||= "Vorpal Generated ActiveRecord::Base Class for #{table_name}. Object ID: #{object_id}"
72
+ end
73
+
74
+ # Overridden because, like #name, the default implementation for anonymous classes is very,
75
+ # very slow.
76
+ def self.to_s
77
+ name
78
+ end
79
+ end
80
+
64
81
  db_class.table_name = table_name
65
82
  db_class
66
83
  end
data/lib/vorpal/engine.rb CHANGED
@@ -3,6 +3,7 @@ require 'vorpal/aggregate_utils'
3
3
  require 'vorpal/db_loader'
4
4
  require 'vorpal/db_driver'
5
5
  require 'vorpal/aggregate_mapper'
6
+ require 'vorpal/exceptions'
6
7
 
7
8
  module Vorpal
8
9
  class Engine
@@ -233,9 +234,4 @@ module Vorpal
233
234
  objects.each { |object| object.id = nil }
234
235
  end
235
236
  end
236
-
237
- class InvalidPrimaryKeyValue < StandardError
238
- end
239
- class InvalidAggregateRoot < StandardError
240
- end
241
237
  end
@@ -0,0 +1,5 @@
1
+ module Vorpal
2
+ class InvalidPrimaryKeyValue < StandardError; end
3
+
4
+ class InvalidAggregateRoot < StandardError; end
5
+ end
@@ -28,6 +28,7 @@ module Vorpal
28
28
  def key(key_object)
29
29
  return nil unless key_object
30
30
  raise "Cannot put entity '#{key_object.inspect}' into IdentityMap without an id." if key_object.id.nil?
31
+ raise "Cannot put entity '#{key_object.inspect}' into IdentityMap without a Class with a name." if key_object.class.name.nil?
31
32
  [key_object.id, key_object.class.name]
32
33
  end
33
34
  end
@@ -1,3 +1,3 @@
1
1
  module Vorpal
2
- VERSION = "0.0.7"
2
+ VERSION = "0.1.0.rc1"
3
3
  end
@@ -1,8 +1,41 @@
1
1
  module DbHelpers
2
+ module_function
3
+
4
+ CONNECTION_SETTINGS = {
5
+ adapter: 'postgresql',
6
+ host: 'localhost',
7
+ database: 'vorpal_test',
8
+ min_messages: 'error',
9
+ # Change the following to reflect your database settings
10
+ # username: 'vorpal',
11
+ # password: 'pass',
12
+ }
13
+
14
+ def ensure_database_exists
15
+ test_database_name = CONNECTION_SETTINGS.fetch(:database)
16
+ if !db_exists?(test_database_name)
17
+ db_connection.create_database(test_database_name)
18
+ end
19
+ end
20
+
21
+ def db_exists?(db_name)
22
+ ActiveRecord::Base.establish_connection(CONNECTION_SETTINGS.merge(database: 'template1'))
23
+
24
+ return db_connection.exec_query("SELECT 1 from pg_database WHERE datname='#{db_name}';").present?
25
+ end
26
+
27
+ def db_connection
28
+ ActiveRecord::Base.connection
29
+ end
30
+
31
+ def establish_connection
32
+ ActiveRecord::Base.establish_connection(CONNECTION_SETTINGS)
33
+ end
34
+
2
35
  # when you change a table's columns, set force to true to re-generate the table in the DB
3
36
  def define_table(table_name, columns, force)
4
- if !ActiveRecord::Base.connection.table_exists?(table_name) || force
5
- ActiveRecord::Base.connection.create_table(table_name, force: true) do |t|
37
+ if !db_connection.table_exists?(table_name) || force
38
+ db_connection.create_table(table_name, force: true) do |t|
6
39
  columns.each do |name, type|
7
40
  t.send(type, name)
8
41
  end
@@ -0,0 +1,26 @@
1
+ require 'ruby-prof'
2
+
3
+ # In order to use these helpers do the following:
4
+ # 1) Add `spec.add_development_dependency "ruby-prof"` to the vorpal.gemspec file.
5
+ # 2) Do a `bundle update`
6
+ # 3) Add `require 'helpers/profile_helpers'` to the spec where you wish to profile.
7
+ module ProfileHelpers
8
+ module_function
9
+
10
+ # Runs a block a given number of times and outputs the profiling results in a 'Call Tree'
11
+ # format suitable for display by a tool like KCacheGrind.
12
+ #
13
+ # - Installing QCacheGrind on OSX: http://nickology.com/2014/04/16/view-xdebug-cachegrind-files-on-mac-os/
14
+ def output_callgrind(description, times=1, &block)
15
+ RubyProf.measure_mode = RubyProf::PROCESS_TIME
16
+ RubyProf.start
17
+
18
+ times.times(&block)
19
+
20
+ result = RubyProf.stop
21
+ printer = RubyProf::CallTreePrinter.new(result)
22
+ File.open("#{description}_#{DateTime.now.strftime("%FT%H:%M:%S%z")}.callgrind", "w") do |file|
23
+ printer.print(file)
24
+ end
25
+ end
26
+ end
@@ -1,18 +1,10 @@
1
1
  require 'active_record'
2
2
  require 'pg'
3
-
4
- # Change the following to reflect your database settings
5
- ActiveRecord::Base.establish_connection(
6
- adapter: 'postgresql',
7
- host: 'localhost',
8
- database: 'vorpal_test',
9
- username: 'vorpal',
10
- password: 'pass',
11
- min_messages: 'error'
12
- )
13
-
14
3
  require 'helpers/db_helpers'
15
4
 
5
+ DbHelpers.ensure_database_exists
6
+ DbHelpers.establish_connection
7
+
16
8
  RSpec.configure do |config|
17
9
  config.include DbHelpers
18
10
 
@@ -65,7 +65,7 @@ describe 'AggregateMapper' do
65
65
  tree = Tree.new(name: 'backyard tree')
66
66
  test_mapper.persist(tree)
67
67
 
68
- tree_db = TreeDB.first
68
+ tree_db = db_class_for(Tree, test_mapper).first
69
69
  expect(tree_db.name).to eq 'backyard tree'
70
70
  end
71
71
 
@@ -77,7 +77,7 @@ describe 'AggregateMapper' do
77
77
 
78
78
  expect(tree.id).to_not be nil
79
79
 
80
- tree_db = TreeDB.first
80
+ tree_db = db_class_for(Tree, test_mapper).first
81
81
  expect(tree_db.id).to eq tree.id
82
82
  end
83
83
 
@@ -98,7 +98,7 @@ describe 'AggregateMapper' do
98
98
  db_driver = Vorpal::DbDriver.new
99
99
  test_mapper = configure(db_driver: db_driver)
100
100
 
101
- tree_db = TreeDB.create!
101
+ tree_db = db_class_for(Tree, test_mapper).create!
102
102
 
103
103
  expect(db_driver).to receive(:update).and_raise('not so good')
104
104
 
@@ -124,7 +124,7 @@ describe 'AggregateMapper' do
124
124
  tree.name = 'big tree'
125
125
  test_mapper.persist(tree)
126
126
 
127
- tree_db = TreeDB.first
127
+ tree_db = db_class_for(Tree, test_mapper).first
128
128
  expect(tree_db.name).to eq 'big tree'
129
129
  end
130
130
 
@@ -151,40 +151,40 @@ describe 'AggregateMapper' do
151
151
  tree.name = 'change it'
152
152
  test_mapper.persist(tree)
153
153
 
154
- expect(TreeDB.count).to eq 1
154
+ expect(db_class_for(Tree, test_mapper).count).to eq 1
155
155
  end
156
156
 
157
157
  it 'removes orphans' do
158
158
  test_mapper = configure
159
159
 
160
- tree_db = TreeDB.create!
161
- BranchDB.create!(tree_id: tree_db.id)
160
+ tree_db = db_class_for(Tree, test_mapper).create!
161
+ db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
162
162
 
163
163
  tree = Tree.new(id: tree_db.id, branches: [])
164
164
 
165
165
  test_mapper.persist(tree)
166
166
 
167
- expect(BranchDB.count).to eq 0
167
+ expect(db_class_for(Branch, test_mapper).count).to eq 0
168
168
  end
169
169
 
170
170
  it 'does not remove orphans from unowned associations' do
171
171
  test_mapper = configure_unowned
172
172
 
173
- tree_db = TreeDB.create!
174
- BranchDB.create!(tree_id: tree_db.id)
173
+ tree_db = db_class_for(Tree, test_mapper).create!
174
+ db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
175
175
 
176
176
  tree = Tree.new(id: tree_db.id, branches: [])
177
177
 
178
178
  test_mapper.persist(tree)
179
179
 
180
- expect(BranchDB.count).to eq 1
180
+ expect(db_class_for(Branch, test_mapper).count).to eq 1
181
181
  end
182
182
  end
183
183
 
184
184
  it 'copies attributes to domain' do
185
185
  test_mapper = configure
186
186
 
187
- tree_db = TreeDB.create! name: 'tree name'
187
+ tree_db = db_class_for(Tree, test_mapper).create! name: 'tree name'
188
188
  tree = test_mapper.load_one(tree_db)
189
189
 
190
190
  expect(tree.id).to eq tree_db.id
@@ -194,7 +194,7 @@ describe 'AggregateMapper' do
194
194
  it 'hydrates ActiveRecord::Base associations' do
195
195
  test_mapper = configure
196
196
 
197
- tree_db = TreeDB.create!
197
+ tree_db = db_class_for(Tree, test_mapper).create!
198
198
  Fissure.create! length: 21, tree_id: tree_db.id
199
199
 
200
200
  tree = test_mapper.load_one(tree_db)
@@ -212,14 +212,14 @@ describe 'AggregateMapper' do
212
212
 
213
213
  test_mapper.persist(tree)
214
214
 
215
- expect(TreeDB.count).to eq 1
215
+ expect(db_class_for(Tree, test_mapper).count).to eq 1
216
216
  end
217
217
 
218
218
  it 'hydrates' do
219
219
  test_mapper = configure_with_cycle
220
220
 
221
- tree_db = TreeDB.create!
222
- BranchDB.create!(length: 50, tree_id: tree_db.id)
221
+ tree_db = db_class_for(Tree, test_mapper).create!
222
+ db_class_for(Branch, test_mapper).create!(length: 50, tree_id: tree_db.id)
223
223
 
224
224
  tree = test_mapper.load_one(tree_db)
225
225
 
@@ -239,15 +239,15 @@ describe 'AggregateMapper' do
239
239
 
240
240
  test_mapper.persist(tree)
241
241
 
242
- expect(BranchDB.count).to eq 2
242
+ expect(db_class_for(Branch, test_mapper).count).to eq 2
243
243
  end
244
244
 
245
245
  it 'hydrates' do
246
246
  test_mapper = configure_recursive
247
247
 
248
- tree_db = TreeDB.create!
249
- long_branch = BranchDB.create!(length: 100, tree_id: tree_db.id)
250
- BranchDB.create!(length: 50, branch_id: long_branch.id)
248
+ tree_db = db_class_for(Tree, test_mapper).create!
249
+ long_branch = db_class_for(Branch, test_mapper).create!(length: 100, tree_id: tree_db.id)
250
+ db_class_for(Branch, test_mapper).create!(length: 50, branch_id: long_branch.id)
251
251
 
252
252
  tree = test_mapper.load_one(tree_db)
253
253
 
@@ -263,7 +263,7 @@ describe 'AggregateMapper' do
263
263
 
264
264
  test_mapper.persist(tree)
265
265
 
266
- trunk_db = TrunkDB.first
266
+ trunk_db = db_class_for(Trunk, test_mapper).first
267
267
  expect(trunk_db.length).to eq 12
268
268
  end
269
269
 
@@ -274,7 +274,7 @@ describe 'AggregateMapper' do
274
274
 
275
275
  test_mapper.persist(tree)
276
276
 
277
- tree_db = TreeDB.first
277
+ tree_db = db_class_for(Tree, test_mapper).first
278
278
  expect(tree_db.trunk_id).to eq trunk.id
279
279
  end
280
280
 
@@ -287,7 +287,7 @@ describe 'AggregateMapper' do
287
287
 
288
288
  trunk.length = 21
289
289
 
290
- expect{ test_mapper.persist(tree) }.to_not change{ TrunkDB.count }
290
+ expect{ test_mapper.persist(tree) }.to_not change{ db_class_for(Trunk, test_mapper).count }
291
291
  end
292
292
 
293
293
  it 'only saves entities that are owned' do
@@ -298,13 +298,13 @@ describe 'AggregateMapper' do
298
298
 
299
299
  test_mapper.persist(tree)
300
300
 
301
- expect(TrunkDB.count).to eq 0
301
+ expect(db_class_for(Trunk, test_mapper).count).to eq 0
302
302
  end
303
303
 
304
304
  it 'hydrates' do
305
305
  test_mapper = configure
306
- trunk_db = TrunkDB.create!(length: 21)
307
- tree_db = TreeDB.create!(trunk_id: trunk_db.id)
306
+ trunk_db = db_class_for(Trunk, test_mapper).create!(length: 21)
307
+ tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
308
308
 
309
309
  new_tree = test_mapper.load_one(tree_db)
310
310
  expect(new_tree.trunk.length).to eq 21
@@ -320,7 +320,7 @@ describe 'AggregateMapper' do
320
320
 
321
321
  test_mapper.persist(tree)
322
322
 
323
- branches = BranchDB.all
323
+ branches = db_class_for(Branch, test_mapper).all
324
324
  expect(branches.size).to eq 2
325
325
  expect(branches.first.length).to eq 100
326
326
  expect(branches.second.length).to eq 3
@@ -333,7 +333,7 @@ describe 'AggregateMapper' do
333
333
 
334
334
  test_mapper.persist(tree)
335
335
 
336
- branches = BranchDB.all
336
+ branches = db_class_for(Branch, test_mapper).all
337
337
  expect(branches.first.tree_id).to eq tree.id
338
338
  end
339
339
 
@@ -349,7 +349,7 @@ describe 'AggregateMapper' do
349
349
 
350
350
  test_mapper.persist(tree)
351
351
 
352
- branches = BranchDB.all
352
+ branches = db_class_for(Branch, test_mapper).all
353
353
  expect(branches.first.length).to eq 120
354
354
  end
355
355
 
@@ -362,14 +362,14 @@ describe 'AggregateMapper' do
362
362
 
363
363
  test_mapper.persist(tree)
364
364
 
365
- expect(BranchDB.count).to eq 0
365
+ expect(db_class_for(Branch, test_mapper).count).to eq 0
366
366
  end
367
367
 
368
368
  it 'hydrates' do
369
369
  test_mapper = configure
370
370
 
371
- tree_db = TreeDB.create!
372
- BranchDB.create!(length: 50, tree_id: tree_db.id)
371
+ tree_db = db_class_for(Tree, test_mapper).create!
372
+ db_class_for(Branch, test_mapper).create!(length: 50, tree_id: tree_db.id)
373
373
 
374
374
  tree = test_mapper.load_one(tree_db)
375
375
 
@@ -385,7 +385,7 @@ describe 'AggregateMapper' do
385
385
 
386
386
  test_mapper.persist(trunk)
387
387
 
388
- expect(TreeDB.first.name).to eq 'big tree'
388
+ expect(db_class_for(Tree, test_mapper).first.name).to eq 'big tree'
389
389
  end
390
390
 
391
391
  it 'saves foreign keys' do
@@ -395,7 +395,7 @@ describe 'AggregateMapper' do
395
395
 
396
396
  test_mapper.persist(trunk)
397
397
 
398
- expect(TreeDB.first.trunk_id).to eq trunk.id
398
+ expect(db_class_for(Tree, test_mapper).first.trunk_id).to eq trunk.id
399
399
  end
400
400
 
401
401
  it 'only saves entities that are owned' do
@@ -405,14 +405,14 @@ describe 'AggregateMapper' do
405
405
 
406
406
  test_mapper.persist(trunk)
407
407
 
408
- expect(TreeDB.count).to eq 0
408
+ expect(db_class_for(Tree, test_mapper).count).to eq 0
409
409
  end
410
410
 
411
411
  it 'hydrates' do
412
412
  test_mapper = configure_has_one
413
413
 
414
- trunk_db = TrunkDB.create!
415
- TreeDB.create!(name: 'big tree', trunk_id: trunk_db.id)
414
+ trunk_db = db_class_for(Trunk, test_mapper).create!
415
+ db_class_for(Tree, test_mapper).create!(name: 'big tree', trunk_id: trunk_db.id)
416
416
 
417
417
  trunk = test_mapper.load_one(trunk_db)
418
418
 
@@ -434,17 +434,17 @@ describe 'AggregateMapper' do
434
434
 
435
435
  test_mapper.persist(tree)
436
436
 
437
- expect(BugDB.find(trunk_bug.id).lives_on_type).to eq Trunk.name
438
- expect(BugDB.find(branch_bug.id).lives_on_type).to eq Branch.name
437
+ expect(db_class_for(Bug, test_mapper).find(trunk_bug.id).lives_on_type).to eq Trunk.name
438
+ expect(db_class_for(Bug, test_mapper).find(branch_bug.id).lives_on_type).to eq Branch.name
439
439
  end
440
440
 
441
441
  it 'restores with has_manys' do
442
442
  test_mapper = configure_polymorphic_has_many
443
443
 
444
- trunk_db = TrunkDB.create!
445
- tree_db = TreeDB.create!(trunk_id: trunk_db.id)
446
- BugDB.create!(name: 'trunk bug', lives_on_id: trunk_db.id, lives_on_type: Trunk.name)
447
- BugDB.create!(name: 'not a trunk bug!', lives_on_id: trunk_db.id, lives_on_type: 'some other table')
444
+ trunk_db = db_class_for(Trunk, test_mapper).create!
445
+ tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
446
+ db_class_for(Bug, test_mapper).create!(name: 'trunk bug', lives_on_id: trunk_db.id, lives_on_type: Trunk.name)
447
+ db_class_for(Bug, test_mapper).create!(name: 'not a trunk bug!', lives_on_id: trunk_db.id, lives_on_type: 'some other table')
448
448
 
449
449
  tree = test_mapper.load_one(tree_db)
450
450
 
@@ -459,8 +459,8 @@ describe 'AggregateMapper' do
459
459
 
460
460
  test_mapper.persist([trunk_bug, branch_bug])
461
461
 
462
- expect(BugDB.find(trunk_bug.id).lives_on_type).to eq Trunk.name
463
- expect(BugDB.find(branch_bug.id).lives_on_type).to eq Branch.name
462
+ expect(db_class_for(Bug, test_mapper).find(trunk_bug.id).lives_on_type).to eq Trunk.name
463
+ expect(db_class_for(Bug, test_mapper).find(branch_bug.id).lives_on_type).to eq Branch.name
464
464
  end
465
465
 
466
466
  it 'saves associations to unowned entities via belongs_to' do
@@ -471,7 +471,7 @@ describe 'AggregateMapper' do
471
471
 
472
472
  test_mapper.persist(trunk_bug)
473
473
 
474
- expect(BugDB.find(trunk_bug.id).lives_on_type).to eq Trunk.name
474
+ expect(db_class_for(Bug, test_mapper).find(trunk_bug.id).lives_on_type).to eq Trunk.name
475
475
  end
476
476
 
477
477
  it 'restores with belongs_tos' do
@@ -479,14 +479,14 @@ describe 'AggregateMapper' do
479
479
 
480
480
  # makes sure that we are using the fk_type to discriminate against
481
481
  # two entities with the same primary key value
482
- trunk_db = TrunkDB.new(length: 99)
482
+ trunk_db = db_class_for(Trunk, test_mapper).new(length: 99)
483
483
  trunk_db.id = 99
484
484
  trunk_db.save!
485
- trunk_bug_db = BugDB.create!(lives_on_id: trunk_db.id, lives_on_type: Trunk.name)
486
- branch_db = BranchDB.new(length: 5)
485
+ trunk_bug_db = db_class_for(Bug, test_mapper).create!(lives_on_id: trunk_db.id, lives_on_type: Trunk.name)
486
+ branch_db = db_class_for(Branch, test_mapper).new(length: 5)
487
487
  branch_db.id = 99
488
488
  branch_db.save!
489
- branch_bug_db = BugDB.create!(lives_on_id: branch_db.id, lives_on_type: Branch.name)
489
+ branch_bug_db = db_class_for(Bug, test_mapper).create!(lives_on_id: branch_db.id, lives_on_type: Branch.name)
490
490
 
491
491
  trunk_bug, branch_bug = test_mapper.load_many([trunk_bug_db, branch_bug_db])
492
492
 
@@ -498,7 +498,7 @@ describe 'AggregateMapper' do
498
498
  test_mapper = configure_ar_polymorphic_belongs_to
499
499
 
500
500
  swamp = Swamp.create!
501
- tree_db = TreeDB.create!(environment_id: swamp.id, environment_type: Swamp.name)
501
+ tree_db = db_class_for(Tree, test_mapper).create!(environment_id: swamp.id, environment_type: Swamp.name)
502
502
 
503
503
  tree = test_mapper.load_one(tree_db)
504
504
 
@@ -510,8 +510,8 @@ describe 'AggregateMapper' do
510
510
  it 'loads many' do
511
511
  test_mapper = configure
512
512
 
513
- TreeDB.create!
514
- tree_db = TreeDB.create!
513
+ db_class_for(Tree, test_mapper).create!
514
+ tree_db = db_class_for(Tree, test_mapper).create!
515
515
 
516
516
  trees = test_mapper.query.where(id: tree_db.id).load_many
517
517
 
@@ -521,8 +521,8 @@ describe 'AggregateMapper' do
521
521
  it 'loads one' do
522
522
  test_mapper = configure
523
523
 
524
- TreeDB.create!
525
- tree_db = TreeDB.create!
524
+ db_class_for(Tree, test_mapper).create!
525
+ tree_db = db_class_for(Tree, test_mapper).create!
526
526
 
527
527
  trees = test_mapper.query.where(id: tree_db.id).load_one
528
528
 
@@ -534,8 +534,8 @@ describe 'AggregateMapper' do
534
534
  it 'maps given db objects' do
535
535
  test_mapper = configure
536
536
 
537
- TreeDB.create!
538
- tree_db = TreeDB.create!
537
+ db_class_for(Tree, test_mapper).create!
538
+ tree_db = db_class_for(Tree, test_mapper).create!
539
539
 
540
540
  trees = test_mapper.load_many([tree_db])
541
541
 
@@ -545,9 +545,9 @@ describe 'AggregateMapper' do
545
545
  it 'only returns roots' do
546
546
  test_mapper = configure
547
547
 
548
- TreeDB.create!
549
- tree_db = TreeDB.create!
550
- BranchDB.create!(tree_id: tree_db.id)
548
+ db_class_for(Tree, test_mapper).create!
549
+ tree_db = db_class_for(Tree, test_mapper).create!
550
+ db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
551
551
 
552
552
  trees = test_mapper.load_many([tree_db])
553
553
 
@@ -559,39 +559,39 @@ describe 'AggregateMapper' do
559
559
  it 'removes the entity from the database' do
560
560
  test_mapper = configure
561
561
 
562
- tree_db = TreeDB.create!
562
+ tree_db = db_class_for(Tree, test_mapper).create!
563
563
 
564
564
  test_mapper.destroy([Tree.new(id: tree_db.id)])
565
565
 
566
- expect(TreeDB.count).to eq 0
566
+ expect(db_class_for(Tree, test_mapper).count).to eq 0
567
567
  end
568
568
 
569
569
  it 'removes has many children from the database' do
570
570
  test_mapper = configure
571
571
 
572
- tree_db = TreeDB.create!
573
- BranchDB.create!(tree_id: tree_db.id)
572
+ tree_db = db_class_for(Tree, test_mapper).create!
573
+ db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
574
574
 
575
575
  test_mapper.destroy(Tree.new(id: tree_db.id))
576
576
 
577
- expect(BranchDB.count).to eq 0
577
+ expect(db_class_for(Branch, test_mapper).count).to eq 0
578
578
  end
579
579
 
580
580
  it 'removes belongs to children from the database' do
581
581
  test_mapper = configure
582
582
 
583
- trunk_db = TrunkDB.create!
584
- tree_db = TreeDB.create!(trunk_id: trunk_db.id)
583
+ trunk_db = db_class_for(Trunk, test_mapper).create!
584
+ tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
585
585
 
586
586
  test_mapper.destroy(Tree.new(id: tree_db.id))
587
587
 
588
- expect(TrunkDB.count).to eq 0
588
+ expect(db_class_for(Trunk, test_mapper).count).to eq 0
589
589
  end
590
590
 
591
591
  it 'removes AR children from the database' do
592
592
  test_mapper = configure
593
593
 
594
- tree_db = TreeDB.create!
594
+ tree_db = db_class_for(Tree, test_mapper).create!
595
595
  Fissure.create!(tree_id: tree_db.id)
596
596
 
597
597
  test_mapper.destroy(Tree.new(id: tree_db.id))
@@ -602,23 +602,23 @@ describe 'AggregateMapper' do
602
602
  it 'leaves unowned belongs to children in the database' do
603
603
  test_mapper = configure_unowned
604
604
 
605
- trunk_db = TrunkDB.create!
606
- tree_db = TreeDB.create!(trunk_id: trunk_db.id)
605
+ trunk_db = db_class_for(Trunk, test_mapper).create!
606
+ tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
607
607
 
608
608
  test_mapper.destroy(Tree.new(id: tree_db.id))
609
609
 
610
- expect(TrunkDB.count).to eq 1
610
+ expect(db_class_for(Trunk, test_mapper).count).to eq 1
611
611
  end
612
612
 
613
613
  it 'leaves unowned has many children in the database' do
614
614
  test_mapper = configure_unowned
615
615
 
616
- tree_db = TreeDB.create!
617
- BranchDB.create!(tree_id: tree_db.id)
616
+ tree_db = db_class_for(Tree, test_mapper).create!
617
+ db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
618
618
 
619
619
  test_mapper.destroy(Tree.new(id: tree_db.id))
620
620
 
621
- expect(BranchDB.count).to eq 1
621
+ expect(db_class_for(Branch, test_mapper).count).to eq 1
622
622
  end
623
623
  end
624
624
 
@@ -626,11 +626,11 @@ describe 'AggregateMapper' do
626
626
  it 'removes the entity from the database' do
627
627
  test_mapper = configure
628
628
 
629
- tree_db = TreeDB.create!
629
+ tree_db = db_class_for(Tree, test_mapper).create!
630
630
 
631
631
  test_mapper.destroy_by_id([tree_db.id])
632
632
 
633
- expect(TreeDB.count).to eq 0
633
+ expect(db_class_for(Tree, test_mapper).count).to eq 0
634
634
  end
635
635
  end
636
636
 
@@ -733,6 +733,10 @@ describe 'AggregateMapper' do
733
733
 
734
734
  private
735
735
 
736
+ def db_class_for(clazz, mapper)
737
+ mapper.engine.mapper_for(clazz).db_class
738
+ end
739
+
736
740
  def configure_polymorphic_has_many
737
741
  engine = Vorpal.define do
738
742
  map Tree do
@@ -3,6 +3,7 @@ require 'vorpal'
3
3
  require 'virtus'
4
4
  require 'activerecord-import/base'
5
5
 
6
+ module Performance
6
7
  describe 'performance' do
7
8
 
8
9
  class Bug
@@ -62,19 +63,12 @@ describe 'performance' do
62
63
 
63
64
  before(:all) do
64
65
  define_table('branches_perf', {length: :decimal, tree_id: :integer, branch_id: :integer}, false)
65
- BranchDB = defineAr('branches_perf')
66
-
67
66
  define_table('bugs_perf', {name: :text, lives_on_id: :integer, lives_on_type: :string}, false)
68
- BugDB = defineAr('bugs_perf')
69
-
70
67
  define_table('trees_perf', {name: :text, trunk_id: :integer}, false)
71
- TreeDB = defineAr('trees_perf')
72
-
73
68
  define_table('trunks_perf', {length: :decimal}, false)
74
- TrunkDB = defineAr('trunks_perf')
75
69
  end
76
70
 
77
- let(:test_mapper) { build_mapper }
71
+ let(:tree_mapper) { build_mapper }
78
72
 
79
73
  # Vorpal 0.0.5:
80
74
  # user system total real
@@ -92,10 +86,10 @@ describe 'performance' do
92
86
  it 'benchmarks all operations' do
93
87
  trees = build_trees(1000)
94
88
  Benchmark.bm(7) do |x|
95
- x.report('create') { test_mapper.persist(trees) }
96
- x.report('update') { test_mapper.persist(trees) }
97
- x.report('load') { test_mapper.load_many(TreeDB.where(id: trees.map(&:id)).all) }
98
- x.report('destroy') { test_mapper.destroy(trees) }
89
+ x.report('create') { tree_mapper.persist(trees) }
90
+ x.report('update') { tree_mapper.persist(trees) }
91
+ x.report('load') { tree_mapper.query.where(id: trees.map(&:id)).load_many }
92
+ x.report('destroy') { tree_mapper.destroy(trees) }
99
93
  end
100
94
  end
101
95
 
@@ -104,39 +98,39 @@ describe 'performance' do
104
98
 
105
99
  puts 'starting persistence benchmark'
106
100
  puts Benchmark.measure {
107
- test_mapper.persist(trees)
101
+ tree_mapper.persist(trees)
108
102
  }
109
103
  end
110
104
 
111
105
  it 'updates aggregates quickly' do
112
106
  trees = build_trees(1000)
113
107
 
114
- test_mapper.persist(trees)
108
+ tree_mapper.persist(trees)
115
109
 
116
110
  puts 'starting update benchmark'
117
111
  puts Benchmark.measure {
118
- test_mapper.persist(trees)
112
+ tree_mapper.persist(trees)
119
113
  }
120
114
  end
121
115
 
122
116
  it 'loads aggregates quickly' do
123
117
  trees = build_trees(1000)
124
- test_mapper.persist(trees)
118
+ tree_mapper.persist(trees)
125
119
  ids = trees.map(&:id)
126
120
 
127
121
  puts 'starting loading benchmark'
128
122
  puts Benchmark.measure {
129
- test_mapper.load_many(TreeDB.where(id: ids).all)
123
+ tree_mapper.query.where(id: ids).load_many
130
124
  }
131
125
  end
132
126
 
133
127
  it 'destroys aggregates quickly' do
134
128
  trees = build_trees(1000)
135
- test_mapper.persist(trees)
129
+ tree_mapper.persist(trees)
136
130
 
137
131
  puts 'starting destruction benchmark'
138
132
  puts Benchmark.measure {
139
- test_mapper.destroy(trees)
133
+ tree_mapper.destroy(trees)
140
134
  }
141
135
  end
142
136
 
@@ -164,26 +158,26 @@ describe 'performance' do
164
158
 
165
159
  def build_mapper
166
160
  engine = Vorpal.define do
167
- map Tree do
161
+ map Tree, table_name: "trees_perf" do
168
162
  attributes :name
169
163
  belongs_to :trunk
170
164
  has_many :branches
171
165
  end
172
166
 
173
- map Trunk do
167
+ map Trunk, table_name: "trunks_perf" do
174
168
  attributes :length
175
169
  has_one :tree
176
170
  has_many :bugs, fk: :lives_on_id, fk_type: :lives_on_type
177
171
  end
178
172
 
179
- map Branch do
173
+ map Branch, table_name: "branches_perf" do
180
174
  attributes :length
181
175
  belongs_to :tree
182
176
  has_many :bugs, fk: :lives_on_id, fk_type: :lives_on_type
183
177
  has_many :branches
184
178
  end
185
179
 
186
- map Bug do
180
+ map Bug, table_name: "bugs_perf" do
187
181
  attributes :name
188
182
  belongs_to :lives_on, fk: :lives_on_id, fk_type: :lives_on_type, child_classes: [Trunk, Branch]
189
183
  end
@@ -191,3 +185,4 @@ describe 'performance' do
191
185
  engine.mapper_for(Tree)
192
186
  end
193
187
  end
188
+ end
@@ -29,31 +29,6 @@ describe Vorpal::ConfigBuilder do
29
29
  end
30
30
  end
31
31
 
32
- describe 'build_db_class' do
33
- it 'sets the class name' do
34
- driver = instance_double(Vorpal::DbDriver)
35
- new_class = Class.new
36
- expect(driver).to receive(:build_db_class).and_return(new_class)
37
-
38
- builder = Vorpal::ConfigBuilder.new(A::B::C::Test, {}, driver)
39
-
40
- builder.build_db_class
41
-
42
- expect(A::B::C::TestDB).to eq(new_class)
43
- end
44
-
45
- it 'does not redefine constants' do
46
- stub_const('A::B::C::TestDB', 1)
47
-
48
- builder = Vorpal::ConfigBuilder.new(A::B::C::Test, {}, nil)
49
-
50
- db_class = builder.build_db_class
51
-
52
- expect(A::B::C::TestDB).to eq(1)
53
- expect(db_class).to eq(1)
54
- end
55
- end
56
-
57
32
  private
58
33
 
59
34
  module A
@@ -5,7 +5,7 @@ require 'vorpal/identity_map'
5
5
  describe Vorpal::IdentityMap do
6
6
  let(:map) { Vorpal::IdentityMap.new }
7
7
 
8
- it 'does not rely on the key objects implementation of hash and eql?' do
8
+ it "does not rely on the key object's implementation of hash and eql?" do
9
9
  funny1 = build_funny_entity(1)
10
10
  map.set(funny1, 'funny 1')
11
11
 
@@ -15,12 +15,23 @@ describe Vorpal::IdentityMap do
15
15
  expect(map.get(funny1)).to eq('funny 1')
16
16
  end
17
17
 
18
- it 'raises an exception when the key object does not have an id set' do
18
+ it "raises an exception when the key object does not have an id set" do
19
19
  entity = build_entity(nil)
20
20
 
21
21
  expect { map.set(entity, 'something') }.to raise_error(/Cannot put entity/)
22
22
  end
23
23
 
24
+ it 'raises an exception when the key object extends a class with no name (such as anonymous classes)' do
25
+ anonymous_class = Class.new do
26
+ attr_accessor :id
27
+ end
28
+
29
+ entity = anonymous_class.new
30
+ entity.id = 1
31
+
32
+ expect { map.set(entity, 'something') }.to raise_error(/Cannot put entity/)
33
+ end
34
+
24
35
  def build_entity(id)
25
36
  entity = Entity.new
26
37
  entity.id = id
data/vorpal.gemspec CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_development_dependency "rake", "~> 10.0"
26
26
  spec.add_development_dependency "rspec", "~> 3.0"
27
- spec.add_development_dependency "activerecord", "~> 4.0.0"
27
+ spec.add_development_dependency "activerecord", "~> 4.0"
28
28
  spec.add_development_dependency "pg", "~> 0.17.0"
29
29
  spec.add_development_dependency "virtus", "~> 1.0"
30
30
  spec.add_development_dependency "activerecord-import", "~> 0.10.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vorpal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Kirby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-14 00:00:00.000000000 Z
11
+ date: 2016-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simple_serializer
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 4.0.0
89
+ version: '4.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 4.0.0
96
+ version: '4.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: pg
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -145,6 +145,7 @@ extensions: []
145
145
  extra_rdoc_files: []
146
146
  files:
147
147
  - ".gitignore"
148
+ - ".rspec"
148
149
  - ".ruby-version"
149
150
  - ".yardopts"
150
151
  - CHANGELOG.md
@@ -162,12 +163,14 @@ files:
162
163
  - lib/vorpal/db_driver.rb
163
164
  - lib/vorpal/db_loader.rb
164
165
  - lib/vorpal/engine.rb
166
+ - lib/vorpal/exceptions.rb
165
167
  - lib/vorpal/identity_map.rb
166
168
  - lib/vorpal/loaded_objects.rb
167
169
  - lib/vorpal/util/array_hash.rb
168
170
  - lib/vorpal/util/hash_initialization.rb
169
171
  - lib/vorpal/version.rb
170
172
  - spec/helpers/db_helpers.rb
173
+ - spec/helpers/profile_helpers.rb
171
174
  - spec/integration_spec_helper.rb
172
175
  - spec/unit_spec_helper.rb
173
176
  - spec/vorpal/acceptance/aggregate_mapper_spec.rb
@@ -193,9 +196,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
193
196
  version: '0'
194
197
  required_rubygems_version: !ruby/object:Gem::Requirement
195
198
  requirements:
196
- - - ">="
199
+ - - ">"
197
200
  - !ruby/object:Gem::Version
198
- version: '0'
201
+ version: 1.3.1
199
202
  requirements: []
200
203
  rubyforge_project:
201
204
  rubygems_version: 2.4.8
@@ -204,6 +207,7 @@ specification_version: 4
204
207
  summary: Separate your domain model from your persistence mechanism.
205
208
  test_files:
206
209
  - spec/helpers/db_helpers.rb
210
+ - spec/helpers/profile_helpers.rb
207
211
  - spec/integration_spec_helper.rb
208
212
  - spec/unit_spec_helper.rb
209
213
  - spec/vorpal/acceptance/aggregate_mapper_spec.rb