vorpal 1.0.0 → 1.2.0

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