vorpal 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Kirby
8
- autorequire:
9
- bindir: bin
8
+ autorequire:
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-26 00:00:00.000000000 Z
11
+ date: 2020-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simple_serializer
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '13'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '13'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -81,61 +81,75 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '3.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: activerecord
84
+ name: appraisal
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '4.0'
89
+ version: '2.2'
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'
96
+ version: '2.2'
97
97
  - !ruby/object:Gem::Dependency
98
- name: pg
98
+ name: activerecord
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: 0.17.0
103
+ version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: 0.17.0
110
+ version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: virtus
112
+ name: pg
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '1.0'
117
+ version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '1.0'
124
+ version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: activerecord-import
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - "~>"
129
+ - - ">="
130
130
  - !ruby/object:Gem::Version
131
- version: 0.10.0
131
+ version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - "~>"
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: codecov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
137
144
  - !ruby/object:Gem::Version
138
- version: 0.10.0
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  description: An ORM framelet that fits on top of ActiveRecord to give you 'Data Mapper'
140
154
  semantics.
141
155
  email:
@@ -144,19 +158,14 @@ executables: []
144
158
  extensions: []
145
159
  extra_rdoc_files: []
146
160
  files:
147
- - ".editorconfig"
148
- - ".gitignore"
149
- - ".rspec"
150
- - ".yardopts"
151
161
  - CHANGELOG.md
152
- - Gemfile
153
162
  - LICENSE.txt
154
163
  - README.md
155
- - Rakefile
156
164
  - lib/vorpal.rb
157
165
  - lib/vorpal/aggregate_mapper.rb
158
166
  - lib/vorpal/aggregate_traversal.rb
159
167
  - lib/vorpal/aggregate_utils.rb
168
+ - lib/vorpal/config/class_config.rb
160
169
  - lib/vorpal/configs.rb
161
170
  - lib/vorpal/db_loader.rb
162
171
  - lib/vorpal/driver/postgresql.rb
@@ -171,26 +180,12 @@ files:
171
180
  - lib/vorpal/util/hash_initialization.rb
172
181
  - lib/vorpal/util/string_utils.rb
173
182
  - lib/vorpal/version.rb
174
- - spec/helpers/db_helpers.rb
175
- - spec/helpers/profile_helpers.rb
176
- - spec/integration_spec_helper.rb
177
- - spec/unit_spec_helper.rb
178
- - spec/vorpal/acceptance/aggregate_mapper_spec.rb
179
- - spec/vorpal/integration/driver/postgresql_spec.rb
180
- - spec/vorpal/performance/performance_spec.rb
181
- - spec/vorpal/unit/configs_spec.rb
182
- - spec/vorpal/unit/db_loader_spec.rb
183
- - spec/vorpal/unit/dsl/config_builder_spec.rb
184
- - spec/vorpal/unit/dsl/defaults_generator_spec.rb
185
- - spec/vorpal/unit/identity_map_spec.rb
186
- - spec/vorpal/unit/loaded_objects_spec.rb
187
- - spec/vorpal/unit/util/string_utils_spec.rb
188
183
  - vorpal.gemspec
189
184
  homepage: https://github.com/nulogy/vorpal
190
185
  licenses:
191
186
  - MIT
192
187
  metadata: {}
193
- post_install_message:
188
+ post_install_message:
194
189
  rdoc_options: []
195
190
  require_paths:
196
191
  - lib
@@ -198,30 +193,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
198
193
  requirements:
199
194
  - - ">="
200
195
  - !ruby/object:Gem::Version
201
- version: 2.1.6
196
+ version: 2.5.7
202
197
  required_rubygems_version: !ruby/object:Gem::Requirement
203
198
  requirements:
204
199
  - - ">="
205
200
  - !ruby/object:Gem::Version
206
201
  version: '0'
207
202
  requirements: []
208
- rubyforge_project:
209
- rubygems_version: 2.7.6
210
- signing_key:
203
+ rubygems_version: 3.1.2
204
+ signing_key:
211
205
  specification_version: 4
212
206
  summary: Separate your domain model from your persistence mechanism.
213
- test_files:
214
- - spec/helpers/db_helpers.rb
215
- - spec/helpers/profile_helpers.rb
216
- - spec/integration_spec_helper.rb
217
- - spec/unit_spec_helper.rb
218
- - spec/vorpal/acceptance/aggregate_mapper_spec.rb
219
- - spec/vorpal/integration/driver/postgresql_spec.rb
220
- - spec/vorpal/performance/performance_spec.rb
221
- - spec/vorpal/unit/configs_spec.rb
222
- - spec/vorpal/unit/db_loader_spec.rb
223
- - spec/vorpal/unit/dsl/config_builder_spec.rb
224
- - spec/vorpal/unit/dsl/defaults_generator_spec.rb
225
- - spec/vorpal/unit/identity_map_spec.rb
226
- - spec/vorpal/unit/loaded_objects_spec.rb
227
- - spec/vorpal/unit/util/string_utils_spec.rb
207
+ test_files: []
@@ -1,13 +0,0 @@
1
- root = true
2
-
3
- [*]
4
-
5
- indent_style = space
6
- indent_size = 2
7
- end_of_line = lf
8
- charset = utf-8
9
- trim_trailing_whitespace = true
10
- insert_final_newline = true
11
-
12
- [*.md]
13
- trim_trailing_whitespace = false
data/.gitignore DELETED
@@ -1,16 +0,0 @@
1
- /.bundle/
2
- /.idea/
3
- /.yardoc
4
- /Gemfile.lock
5
- /_yardoc/
6
- /coverage/
7
- /doc/
8
- /pkg/
9
- /spec/reports/
10
- /tmp/
11
- *.bundle
12
- *.so
13
- *.o
14
- *.a
15
- mkmf.log
16
- /projectFilesBackup
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --colour
data/.yardopts DELETED
@@ -1 +0,0 @@
1
- --no-private -m markdown lib/**/*.*
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in vorpal.gemspec
4
- gemspec
data/Rakefile DELETED
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env rake
2
- begin
3
- require "bundler/gem_tasks"
4
- rescue LoadError
5
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks associated with creating new versions of the gem.'
6
- end
7
-
8
- require 'rspec/core/rake_task'
9
- RSpec::Core::RakeTask.new(:spec)
10
- task :default => :spec
@@ -1,51 +0,0 @@
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
-
35
- # when you change a table's columns, set force to true to re-generate the table in the DB
36
- def define_table(table_name, columns, force)
37
- if !db_connection.table_exists?(table_name) || force
38
- db_connection.create_table(table_name, force: true) do |t|
39
- columns.each do |name, type|
40
- t.send(type, name)
41
- end
42
- end
43
- end
44
- end
45
-
46
- def defineAr(table_name)
47
- Class.new(ActiveRecord::Base) do
48
- self.table_name = table_name
49
- end
50
- end
51
- end
@@ -1,26 +0,0 @@
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,36 +0,0 @@
1
- require 'active_record'
2
- require 'pg'
3
- require 'helpers/db_helpers'
4
-
5
- DbHelpers.ensure_database_exists
6
- DbHelpers.establish_connection
7
-
8
- RSpec.configure do |config|
9
- config.include DbHelpers
10
-
11
- # implements `use_transactional_fixtures = true`
12
- config.before(:each) do
13
- connection = ActiveRecord::Base.connection
14
- if ActiveRecord::VERSION::MAJOR == 3
15
- # from lib/active_record/fixtures.rb
16
- connection.increment_open_transactions
17
- connection.transaction_joinable = false
18
- connection.begin_db_transaction
19
- else
20
- connection.begin_transaction(joinable: false)
21
- end
22
- end
23
-
24
- config.after(:each) do
25
- connection = ActiveRecord::Base.connection
26
- if ActiveRecord::VERSION::MAJOR == 3
27
- if connection.open_transactions != 0
28
- connection.rollback_db_transaction
29
- connection.decrement_open_transactions
30
- end
31
- else
32
- connection.rollback_transaction if connection.transaction_open?
33
- end
34
- ActiveRecord::Base.clear_active_connections!
35
- end
36
- end
File without changes
@@ -1,911 +0,0 @@
1
- require 'integration_spec_helper'
2
- require 'vorpal'
3
- require 'virtus'
4
- require 'activerecord-import/base'
5
-
6
- describe 'AggregateMapper' do
7
-
8
- # for testing polymorphic associations
9
- class Bug
10
- include Virtus.model
11
-
12
- attribute :id, Integer
13
- attribute :name, String
14
- attribute :lives_on, Object
15
- end
16
-
17
- class Tree; end
18
-
19
- class Trunk
20
- include Virtus.model
21
-
22
- attribute :id, Integer
23
- attribute :length, Decimal
24
- attribute :bugs, Array[Bug]
25
- attribute :tree, Tree
26
- end
27
-
28
- class Branch
29
- include Virtus.model
30
-
31
- attribute :id, Integer
32
- attribute :length, Decimal
33
- attribute :tree, Tree
34
- attribute :branches, Array[Branch]
35
- attribute :bugs, Array[Bug]
36
- end
37
-
38
- class Fissure < ActiveRecord::Base; end
39
- class Swamp < ActiveRecord::Base; end
40
-
41
- class Tree
42
- include Virtus.model
43
-
44
- attribute :id, Integer
45
- attribute :name, String
46
- attribute :trunk, Trunk
47
- attribute :environment, Object
48
- attribute :fissures, Array[Fissure]
49
- attribute :branches, Array[Branch]
50
- end
51
-
52
- before(:all) do
53
- define_table('branches', {length: :decimal, tree_id: :integer, branch_id: :integer}, false)
54
- define_table('bugs', {name: :text, lives_on_id: :integer, lives_on_type: :string}, false)
55
- define_table('fissures', {length: :decimal, tree_id: :integer}, false)
56
- define_table('trees', {name: :text, trunk_id: :integer, environment_id: :integer, environment_type: :string}, false)
57
- define_table('trunks', {length: :decimal}, false)
58
- define_table('swamps', {}, false)
59
- end
60
-
61
- describe 'new records' do
62
- it 'saves attributes' do
63
- test_mapper = configure
64
-
65
- tree = Tree.new(name: 'backyard tree')
66
- test_mapper.persist(tree)
67
-
68
- tree_db = db_class_for(Tree, test_mapper).first
69
- expect(tree_db.name).to eq 'backyard tree'
70
- end
71
-
72
- it 'sets the id when first saved' do
73
- test_mapper = configure
74
-
75
- tree = Tree.new()
76
- test_mapper.persist(tree)
77
-
78
- expect(tree.id).to_not be nil
79
-
80
- tree_db = db_class_for(Tree, test_mapper).first
81
- expect(tree_db.id).to eq tree.id
82
- end
83
-
84
- it 'saves AR::Base objects' do
85
- test_mapper = configure
86
-
87
- fissure = Fissure.new(length: 21)
88
- tree = Tree.new(fissures: [fissure])
89
-
90
- test_mapper.persist(tree)
91
-
92
- expect(Fissure.first.length).to eq 21
93
- end
94
- end
95
-
96
- describe 'on error' do
97
- it 'nils ids of new objects' do
98
- db_driver = Vorpal::Driver::Postgresql.new
99
- test_mapper = configure(db_driver: db_driver)
100
-
101
- tree_db = db_class_for(Tree, test_mapper).create!
102
-
103
- expect(db_driver).to receive(:update).and_raise('not so good')
104
-
105
- fissure = Fissure.new
106
- tree = Tree.new(id: tree_db.id, fissures: [fissure])
107
-
108
- expect {
109
- test_mapper.persist(tree)
110
- }.to raise_error(Exception)
111
-
112
- expect(fissure.id).to eq nil
113
- expect(tree.id).to_not eq nil
114
- end
115
- end
116
-
117
- describe 'existing records' do
118
- it 'updates attributes' do
119
- test_mapper = configure
120
-
121
- tree = Tree.new(name: 'little tree')
122
- test_mapper.persist(tree)
123
-
124
- tree.name = 'big tree'
125
- test_mapper.persist(tree)
126
-
127
- tree_db = db_class_for(Tree, test_mapper).first
128
- expect(tree_db.name).to eq 'big tree'
129
- end
130
-
131
- it 'does not change the id on update' do
132
- test_mapper = configure
133
-
134
- tree = Tree.new
135
- test_mapper.persist(tree)
136
-
137
- original_id = tree.id
138
-
139
- tree.name = 'change it'
140
- test_mapper.persist(tree)
141
-
142
- expect(tree.id).to eq original_id
143
- end
144
-
145
- it 'does not create additional records' do
146
- test_mapper = configure
147
-
148
- tree = Tree.new
149
- test_mapper.persist(tree)
150
-
151
- tree.name = 'change it'
152
- test_mapper.persist(tree)
153
-
154
- expect(db_class_for(Tree, test_mapper).count).to eq 1
155
- end
156
-
157
- it 'removes orphans' do
158
- test_mapper = configure
159
-
160
- tree_db = db_class_for(Tree, test_mapper).create!
161
- db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
162
-
163
- tree = Tree.new(id: tree_db.id, branches: [])
164
-
165
- test_mapper.persist(tree)
166
-
167
- expect(db_class_for(Branch, test_mapper).count).to eq 0
168
- end
169
-
170
- it 'does not remove orphans from unowned associations' do
171
- test_mapper = configure_unowned
172
-
173
- tree_db = db_class_for(Tree, test_mapper).create!
174
- db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
175
-
176
- tree = Tree.new(id: tree_db.id, branches: [])
177
-
178
- test_mapper.persist(tree)
179
-
180
- expect(db_class_for(Branch, test_mapper).count).to eq 1
181
- end
182
- end
183
-
184
- it 'copies attributes to domain' do
185
- test_mapper = configure
186
-
187
- tree_db = db_class_for(Tree, test_mapper).create! name: 'tree name'
188
- tree = test_mapper.load_one(tree_db)
189
-
190
- expect(tree.id).to eq tree_db.id
191
- expect(tree.name).to eq 'tree name'
192
- end
193
-
194
- it 'hydrates ActiveRecord::Base associations' do
195
- test_mapper = configure
196
-
197
- tree_db = db_class_for(Tree, test_mapper).create!
198
- Fissure.create! length: 21, tree_id: tree_db.id
199
-
200
- tree = test_mapper.load_one(tree_db)
201
-
202
- expect(tree.fissures.first.length).to eq 21
203
- end
204
-
205
- describe 'cycles' do
206
- it 'persists' do
207
- test_mapper = configure_with_cycle
208
-
209
- tree = Tree.new
210
- long_branch = Branch.new(length: 100, tree: tree)
211
- tree.branches << long_branch
212
-
213
- test_mapper.persist(tree)
214
-
215
- expect(db_class_for(Tree, test_mapper).count).to eq 1
216
- end
217
-
218
- it 'hydrates' do
219
- test_mapper = configure_with_cycle
220
-
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
-
224
- tree = test_mapper.load_one(tree_db)
225
-
226
- expect(tree).to be tree.branches.first.tree
227
- end
228
- end
229
-
230
- describe 'recursive associations' do
231
- it 'persists' do
232
- test_mapper = configure_recursive
233
-
234
- tree = Tree.new
235
- long_branch = Branch.new(length: 100, tree: tree)
236
- tree.branches << long_branch
237
- short_branch = Branch.new(length: 50, tree: tree)
238
- long_branch.branches << short_branch
239
-
240
- test_mapper.persist(tree)
241
-
242
- expect(db_class_for(Branch, test_mapper).count).to eq 2
243
- end
244
-
245
- it 'hydrates' do
246
- test_mapper = configure_recursive
247
-
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
-
252
- tree = test_mapper.load_one(tree_db)
253
-
254
- expect(tree.branches.first.branches.first.length).to eq 50
255
- end
256
- end
257
-
258
- describe 'belongs_to associations' do
259
- it 'saves attributes' do
260
- test_mapper = configure
261
- trunk = Trunk.new(length: 12)
262
- tree = Tree.new(trunk: trunk)
263
-
264
- test_mapper.persist(tree)
265
-
266
- trunk_db = db_class_for(Trunk, test_mapper).first
267
- expect(trunk_db.length).to eq 12
268
- end
269
-
270
- it 'saves foreign keys' do
271
- test_mapper = configure
272
- trunk = Trunk.new
273
- tree = Tree.new(trunk: trunk)
274
-
275
- test_mapper.persist(tree)
276
-
277
- tree_db = db_class_for(Tree, test_mapper).first
278
- expect(tree_db.trunk_id).to eq trunk.id
279
- end
280
-
281
- it 'updating does not create additional rows' do
282
- test_mapper = configure
283
- trunk = Trunk.new
284
- tree = Tree.new(trunk: trunk)
285
-
286
- test_mapper.persist(tree)
287
-
288
- trunk.length = 21
289
-
290
- expect{ test_mapper.persist(tree) }.to_not change{ db_class_for(Trunk, test_mapper).count }
291
- end
292
-
293
- it 'only saves entities that are owned' do
294
- test_mapper = configure_unowned
295
-
296
- trunk = Trunk.new
297
- tree = Tree.new(trunk: trunk)
298
-
299
- test_mapper.persist(tree)
300
-
301
- expect(db_class_for(Trunk, test_mapper).count).to eq 0
302
- end
303
-
304
- it 'hydrates' do
305
- test_mapper = configure
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
-
309
- new_tree = test_mapper.load_one(tree_db)
310
- expect(new_tree.trunk.length).to eq 21
311
- end
312
- end
313
-
314
- describe 'has_many associations' do
315
- it 'saves' do
316
- test_mapper = configure
317
- tree = Tree.new
318
- tree.branches << Branch.new(length: 100)
319
- tree.branches << Branch.new(length: 3)
320
-
321
- test_mapper.persist(tree)
322
-
323
- branches = db_class_for(Branch, test_mapper).all
324
- expect(branches.size).to eq 2
325
- expect(branches.first.length).to eq 100
326
- expect(branches.second.length).to eq 3
327
- end
328
-
329
- it 'saves foreign keys' do
330
- test_mapper = configure
331
- tree = Tree.new
332
- tree.branches << Branch.new(length: 100)
333
-
334
- test_mapper.persist(tree)
335
-
336
- branches = db_class_for(Branch, test_mapper).all
337
- expect(branches.first.tree_id).to eq tree.id
338
- end
339
-
340
- it 'updates' do
341
- test_mapper = configure
342
- tree = Tree.new
343
- long_branch = Branch.new(length: 100)
344
- tree.branches << long_branch
345
-
346
- test_mapper.persist(tree)
347
-
348
- long_branch.length = 120
349
-
350
- test_mapper.persist(tree)
351
-
352
- branches = db_class_for(Branch, test_mapper).all
353
- expect(branches.first.length).to eq 120
354
- end
355
-
356
- it 'only saves entities that are owned' do
357
- test_mapper = configure_unowned
358
-
359
- tree = Tree.new
360
- long_branch = Branch.new(length: 100)
361
- tree.branches << long_branch
362
-
363
- test_mapper.persist(tree)
364
-
365
- expect(db_class_for(Branch, test_mapper).count).to eq 0
366
- end
367
-
368
- it 'hydrates' do
369
- test_mapper = configure
370
-
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
-
374
- tree = test_mapper.load_one(tree_db)
375
-
376
- expect(tree.branches.first.length).to eq 50
377
- end
378
- end
379
-
380
- describe 'has_one associations' do
381
- it 'saves' do
382
- test_mapper = configure_has_one
383
- tree = Tree.new(name: 'big tree')
384
- trunk = Trunk.new(tree: tree)
385
-
386
- test_mapper.persist(trunk)
387
-
388
- expect(db_class_for(Tree, test_mapper).first.name).to eq 'big tree'
389
- end
390
-
391
- it 'saves foreign keys' do
392
- test_mapper = configure_has_one
393
- tree = Tree.new(name: 'big tree')
394
- trunk = Trunk.new(tree: tree)
395
-
396
- test_mapper.persist(trunk)
397
-
398
- expect(db_class_for(Tree, test_mapper).first.trunk_id).to eq trunk.id
399
- end
400
-
401
- it 'only saves entities that are owned' do
402
- test_mapper = configure_unowned_has_one
403
- tree = Tree.new
404
- trunk = Trunk.new(tree: tree)
405
-
406
- test_mapper.persist(trunk)
407
-
408
- expect(db_class_for(Tree, test_mapper).count).to eq 0
409
- end
410
-
411
- it 'hydrates' do
412
- test_mapper = configure_has_one
413
-
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
-
417
- trunk = test_mapper.load_one(trunk_db)
418
-
419
- expect(trunk.tree.name).to eq 'big tree'
420
- end
421
- end
422
-
423
- describe 'polymorphic associations' do
424
- it 'saves with has_manys' do
425
- test_mapper = configure_polymorphic_has_many
426
- trunk = Trunk.new
427
- branch = Branch.new
428
- tree = Tree.new(trunk: trunk, branches: [branch])
429
-
430
- trunk_bug = Bug.new
431
- trunk.bugs << trunk_bug
432
- branch_bug = Bug.new
433
- branch.bugs << branch_bug
434
-
435
- test_mapper.persist(tree)
436
-
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
- end
440
-
441
- it 'restores with has_manys' do
442
- test_mapper = configure_polymorphic_has_many
443
-
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
-
449
- tree = test_mapper.load_one(tree_db)
450
-
451
- expect(tree.trunk.bugs.map(&:name)).to eq ['trunk bug']
452
- end
453
-
454
- it 'saves with belongs_tos' do
455
- test_mapper = configure_polymorphic_belongs_to
456
-
457
- trunk_bug = Bug.new(lives_on: Trunk.new)
458
- branch_bug = Bug.new(lives_on: Branch.new)
459
-
460
- test_mapper.persist([trunk_bug, branch_bug])
461
-
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
- end
465
-
466
- it 'saves associations to unowned entities via belongs_to' do
467
- test_mapper = configure_unowned_polymorphic_belongs_to
468
- trunk = Trunk.new
469
-
470
- trunk_bug = Bug.new(lives_on: trunk)
471
-
472
- test_mapper.persist(trunk_bug)
473
-
474
- expect(db_class_for(Bug, test_mapper).find(trunk_bug.id).lives_on_type).to eq Trunk.name
475
- end
476
-
477
- it 'restores with belongs_tos' do
478
- test_mapper = configure_polymorphic_belongs_to
479
-
480
- # makes sure that we are using the fk_type to discriminate against
481
- # two entities with the same primary key value
482
- trunk_db = db_class_for(Trunk, test_mapper).new(length: 99)
483
- trunk_db.id = 99
484
- trunk_db.save!
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
- branch_db.id = 99
488
- branch_db.save!
489
- branch_bug_db = db_class_for(Bug, test_mapper).create!(lives_on_id: branch_db.id, lives_on_type: Branch.name)
490
-
491
- trunk_bug, branch_bug = test_mapper.load_many([trunk_bug_db, branch_bug_db])
492
-
493
- expect(trunk_bug.lives_on.length).to eq 99
494
- expect(branch_bug.lives_on.length).to eq 5
495
- end
496
-
497
- it 'restores active record objects' do
498
- test_mapper = configure_ar_polymorphic_belongs_to
499
-
500
- swamp = Swamp.create!
501
- tree_db = db_class_for(Tree, test_mapper).create!(environment_id: swamp.id, environment_type: Swamp.name)
502
-
503
- tree = test_mapper.load_one(tree_db)
504
-
505
- expect(tree.environment).to eq swamp
506
- end
507
- end
508
-
509
- describe 'arel' do
510
- it 'loads many' do
511
- test_mapper = configure
512
-
513
- db_class_for(Tree, test_mapper).create!
514
- tree_db = db_class_for(Tree, test_mapper).create!
515
-
516
- trees = test_mapper.query.where(id: tree_db.id).load_many
517
-
518
- expect(trees.map(&:id)).to eq [tree_db.id]
519
- end
520
-
521
- it 'loads one' do
522
- test_mapper = configure
523
-
524
- db_class_for(Tree, test_mapper).create!
525
- tree_db = db_class_for(Tree, test_mapper).create!
526
-
527
- trees = test_mapper.query.where(id: tree_db.id).load_one
528
-
529
- expect(trees.id).to eq tree_db.id
530
- end
531
- end
532
-
533
- describe 'load_many' do
534
- it 'maps given db objects' do
535
- test_mapper = configure
536
-
537
- db_class_for(Tree, test_mapper).create!
538
- tree_db = db_class_for(Tree, test_mapper).create!
539
-
540
- trees = test_mapper.load_many([tree_db])
541
-
542
- expect(trees.map(&:id)).to eq [tree_db.id]
543
- end
544
-
545
- it 'only returns roots' do
546
- test_mapper = configure
547
-
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
-
552
- trees = test_mapper.load_many([tree_db])
553
-
554
- expect(trees.map(&:id)).to eq [tree_db.id]
555
- end
556
- end
557
-
558
- describe 'destroy' do
559
- it 'removes the entity from the database' do
560
- test_mapper = configure
561
-
562
- tree_db = db_class_for(Tree, test_mapper).create!
563
-
564
- test_mapper.destroy([Tree.new(id: tree_db.id)])
565
-
566
- expect(db_class_for(Tree, test_mapper).count).to eq 0
567
- end
568
-
569
- it 'removes has many children from the database' do
570
- test_mapper = configure
571
-
572
- tree_db = db_class_for(Tree, test_mapper).create!
573
- db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
574
-
575
- test_mapper.destroy(Tree.new(id: tree_db.id))
576
-
577
- expect(db_class_for(Branch, test_mapper).count).to eq 0
578
- end
579
-
580
- it 'removes belongs to children from the database' do
581
- test_mapper = configure
582
-
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
-
586
- test_mapper.destroy(Tree.new(id: tree_db.id))
587
-
588
- expect(db_class_for(Trunk, test_mapper).count).to eq 0
589
- end
590
-
591
- it 'removes AR children from the database' do
592
- test_mapper = configure
593
-
594
- tree_db = db_class_for(Tree, test_mapper).create!
595
- Fissure.create!(tree_id: tree_db.id)
596
-
597
- test_mapper.destroy(Tree.new(id: tree_db.id))
598
-
599
- expect(Fissure.count).to eq 0
600
- end
601
-
602
- it 'leaves unowned belongs to children in the database' do
603
- test_mapper = configure_unowned
604
-
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
-
608
- test_mapper.destroy(Tree.new(id: tree_db.id))
609
-
610
- expect(db_class_for(Trunk, test_mapper).count).to eq 1
611
- end
612
-
613
- it 'leaves unowned has many children in the database' do
614
- test_mapper = configure_unowned
615
-
616
- tree_db = db_class_for(Tree, test_mapper).create!
617
- db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
618
-
619
- test_mapper.destroy(Tree.new(id: tree_db.id))
620
-
621
- expect(db_class_for(Branch, test_mapper).count).to eq 1
622
- end
623
- end
624
-
625
- describe 'destroy_by_id' do
626
- it 'removes the entity from the database' do
627
- test_mapper = configure
628
-
629
- tree_db = db_class_for(Tree, test_mapper).create!
630
-
631
- test_mapper.destroy_by_id([tree_db.id])
632
-
633
- expect(db_class_for(Tree, test_mapper).count).to eq 0
634
- end
635
- end
636
-
637
- describe 'non-existent values' do
638
- it 'load_many returns an empty array when given an empty array' do
639
- test_mapper = configure
640
-
641
- results = test_mapper.load_many([])
642
- expect(results).to eq []
643
- end
644
-
645
- it 'load_many throws an exception when given a nil db_object' do
646
- test_mapper = configure
647
-
648
- expect {
649
- test_mapper.load_many([nil])
650
- }.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
651
- end
652
-
653
- it 'load_one returns nil when given nil' do
654
- test_mapper = configure
655
-
656
- result = test_mapper.load_one(nil)
657
- expect(result).to eq nil
658
- end
659
-
660
- it 'persist ignores empty arrays' do
661
- test_mapper = configure
662
-
663
- results = test_mapper.persist([])
664
- expect(results).to eq []
665
- end
666
-
667
- it 'persist throws an exception when given a collection with a nil root' do
668
- test_mapper = configure
669
- expect {
670
- test_mapper.persist([nil])
671
- }.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
672
- end
673
-
674
- it 'persist throws an exception when given a nil root' do
675
- test_mapper = configure
676
- expect {
677
- test_mapper.persist(nil)
678
- }.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
679
- end
680
-
681
- it 'destroy ignores empty arrays' do
682
- test_mapper = configure
683
-
684
- results = test_mapper.destroy([])
685
- expect(results).to eq []
686
- end
687
-
688
- it 'destroy throws an exception when given a nil root' do
689
- test_mapper = configure
690
-
691
- expect {
692
- test_mapper.destroy(nil)
693
- }.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
694
- end
695
-
696
- it 'destroy throws an exception when given a collection with a nil root' do
697
- test_mapper = configure
698
-
699
- expect {
700
- test_mapper.destroy([nil])
701
- }.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
702
- end
703
-
704
- it 'destroy_by_id ignores empty arrays' do
705
- test_mapper = configure
706
-
707
- results = test_mapper.destroy_by_id([])
708
- expect(results).to eq []
709
- end
710
-
711
- it 'destroy_by_id ignores ids that do not exist' do
712
- test_mapper = configure
713
-
714
- test_mapper.destroy_by_id([99])
715
- end
716
-
717
- it 'destroy_by_id throws an exception when given a collection with a nil id' do
718
- test_mapper = configure
719
-
720
- expect {
721
- test_mapper.destroy_by_id([nil])
722
- }.to raise_error(Vorpal::InvalidPrimaryKeyValue, "Nil primary key values are not allowed.")
723
- end
724
-
725
- it 'destroy_by_id throws an exception when given a nil id' do
726
- test_mapper = configure
727
-
728
- expect {
729
- test_mapper.destroy_by_id(nil)
730
- }.to raise_error(Vorpal::InvalidPrimaryKeyValue, "Nil primary key values are not allowed.")
731
- end
732
- end
733
-
734
- private
735
-
736
- def db_class_for(clazz, mapper)
737
- mapper.engine.mapper_for(clazz).db_class
738
- end
739
-
740
- def configure_polymorphic_has_many
741
- engine = Vorpal.define do
742
- map Tree do
743
- attributes :name
744
- has_many :branches
745
- belongs_to :trunk
746
- end
747
-
748
- map Trunk do
749
- attributes :length
750
- has_many :bugs, fk: :lives_on_id, fk_type: :lives_on_type
751
- end
752
-
753
- map Branch do
754
- attributes :length
755
- has_many :bugs, fk: :lives_on_id, fk_type: :lives_on_type
756
- end
757
-
758
- map Bug do
759
- attributes :name
760
- end
761
- end
762
- engine.mapper_for(Tree)
763
- end
764
-
765
- def configure_polymorphic_belongs_to
766
- engine = Vorpal.define do
767
- map Bug do
768
- attributes :name
769
- belongs_to :lives_on, fk: :lives_on_id, fk_type: :lives_on_type, child_classes: [Trunk, Branch]
770
- end
771
-
772
- map Trunk do
773
- attributes :length
774
- end
775
-
776
- map Branch do
777
- attributes :length
778
- end
779
- end
780
- engine.mapper_for(Bug)
781
- end
782
-
783
- def configure_ar_polymorphic_belongs_to
784
- engine = Vorpal.define do
785
- map Tree do
786
- attributes :name
787
- belongs_to :environment, owned: false, fk: :environment_id, fk_type: :environment_type, child_class: Swamp
788
- end
789
-
790
- map Swamp, to: Swamp
791
- end
792
- engine.mapper_for(Tree)
793
- end
794
-
795
- def configure_unowned_polymorphic_belongs_to
796
- engine = Vorpal.define do
797
- map Bug do
798
- attributes :name
799
- belongs_to :lives_on, owned: false, fk: :lives_on_id, fk_type: :lives_on_type, child_classes: [Trunk, Branch]
800
- end
801
-
802
- map Trunk do
803
- attributes :length
804
- end
805
-
806
- map Branch do
807
- attributes :length
808
- end
809
- end
810
- engine.mapper_for(Bug)
811
- end
812
-
813
- def configure_unowned
814
- engine = Vorpal.define do
815
- map Tree do
816
- attributes :name
817
- has_many :branches, owned: false
818
- belongs_to :trunk, owned: false
819
- end
820
-
821
- map Trunk do
822
- attributes :length
823
- end
824
-
825
- map Branch do
826
- attributes :length
827
- end
828
- end
829
- engine.mapper_for(Tree)
830
- end
831
-
832
- def configure_recursive
833
- engine = Vorpal.define do
834
- map Branch do
835
- attributes :length
836
- has_many :branches
837
- end
838
-
839
- map Tree do
840
- attributes :name
841
- has_many :branches
842
- end
843
- end
844
- engine.mapper_for(Tree)
845
- end
846
-
847
- def configure_with_cycle
848
- engine = Vorpal.define do
849
- map Branch do
850
- attributes :length
851
- belongs_to :tree
852
- end
853
-
854
- map Tree do
855
- attributes :name
856
- has_many :branches
857
- end
858
- end
859
- engine.mapper_for(Tree)
860
- end
861
-
862
- def configure(options={})
863
- engine = Vorpal.define(options) do
864
- map Tree do
865
- attributes :name
866
- belongs_to :trunk
867
- has_many :fissures
868
- has_many :branches
869
- end
870
-
871
- map Trunk do
872
- attributes :length
873
- end
874
-
875
- map Branch do
876
- attributes :length
877
- end
878
-
879
- map Fissure, to: Fissure
880
- end
881
- engine.mapper_for(Tree)
882
- end
883
-
884
- def configure_has_one
885
- engine = Vorpal.define do
886
- map Trunk do
887
- attributes :length
888
- has_one :tree
889
- end
890
-
891
- map Tree do
892
- attributes :name
893
- end
894
- end
895
- engine.mapper_for(Trunk)
896
- end
897
-
898
- def configure_unowned_has_one
899
- engine = Vorpal.define do
900
- map Trunk do
901
- attributes :length
902
- has_one :tree, owned: false
903
- end
904
-
905
- map Tree do
906
- attributes :name
907
- end
908
- end
909
- engine.mapper_for(Trunk)
910
- end
911
- end