vorpal 0.0.7 → 0.1.0.rc1

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 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