vorpal 1.0.3 → 1.1.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -10
  3. data/lib/vorpal/aggregate_mapper.rb +11 -0
  4. data/lib/vorpal/driver/postgresql.rb +39 -3
  5. data/lib/vorpal/version.rb +1 -1
  6. data/vorpal.gemspec +4 -3
  7. metadata +9 -59
  8. data/.editorconfig +0 -13
  9. data/.envrc +0 -4
  10. data/.gitignore +0 -16
  11. data/.rspec +0 -1
  12. data/.ruby-version +0 -1
  13. data/.travis.yml +0 -18
  14. data/.yardopts +0 -1
  15. data/Appraisals +0 -18
  16. data/Gemfile +0 -4
  17. data/Rakefile +0 -39
  18. data/bin/appraisal +0 -29
  19. data/bin/rake +0 -29
  20. data/bin/rspec +0 -29
  21. data/docker-compose.yml +0 -19
  22. data/gemfiles/rails_5_1.gemfile +0 -11
  23. data/gemfiles/rails_5_1.gemfile.lock +0 -101
  24. data/gemfiles/rails_5_2.gemfile +0 -11
  25. data/gemfiles/rails_5_2.gemfile.lock +0 -101
  26. data/gemfiles/rails_6_0.gemfile +0 -9
  27. data/gemfiles/rails_6_0.gemfile.lock +0 -101
  28. data/spec/acceptance/vorpal/aggregate_mapper_spec.rb +0 -910
  29. data/spec/helpers/codecov_helper.rb +0 -7
  30. data/spec/helpers/db_helpers.rb +0 -69
  31. data/spec/helpers/profile_helpers.rb +0 -26
  32. data/spec/integration/vorpal/driver/postgresql_spec.rb +0 -42
  33. data/spec/integration_spec_helper.rb +0 -29
  34. data/spec/performance/vorpal/performance_spec.rb +0 -305
  35. data/spec/unit/vorpal/configs_spec.rb +0 -117
  36. data/spec/unit/vorpal/db_loader_spec.rb +0 -103
  37. data/spec/unit/vorpal/dsl/config_builder_spec.rb +0 -18
  38. data/spec/unit/vorpal/dsl/defaults_generator_spec.rb +0 -75
  39. data/spec/unit/vorpal/identity_map_spec.rb +0 -62
  40. data/spec/unit/vorpal/loaded_objects_spec.rb +0 -22
  41. data/spec/unit/vorpal/util/string_utils_spec.rb +0 -25
  42. data/spec/unit_spec_helper.rb +0 -1
data/bin/rake DELETED
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- #
5
- # This file was generated by Bundler.
6
- #
7
- # The application 'rake' is installed as part of a gem, and
8
- # this file is here to facilitate running it.
9
- #
10
-
11
- require "pathname"
12
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
- Pathname.new(__FILE__).realpath)
14
-
15
- bundle_binstub = File.expand_path("../bundle", __FILE__)
16
-
17
- if File.file?(bundle_binstub)
18
- if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
- load(bundle_binstub)
20
- else
21
- abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
- Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
- end
24
- end
25
-
26
- require "rubygems"
27
- require "bundler/setup"
28
-
29
- load Gem.bin_path("rake", "rake")
data/bin/rspec DELETED
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- #
5
- # This file was generated by Bundler.
6
- #
7
- # The application 'rspec' is installed as part of a gem, and
8
- # this file is here to facilitate running it.
9
- #
10
-
11
- require "pathname"
12
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
- Pathname.new(__FILE__).realpath)
14
-
15
- bundle_binstub = File.expand_path("../bundle", __FILE__)
16
-
17
- if File.file?(bundle_binstub)
18
- if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
- load(bundle_binstub)
20
- else
21
- abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
- Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
- end
24
- end
25
-
26
- require "rubygems"
27
- require "bundler/setup"
28
-
29
- load Gem.bin_path("rspec-core", "rspec")
@@ -1,19 +0,0 @@
1
- version: "3.6"
2
-
3
- services:
4
- vorpal_postgres:
5
- hostname: vorpal_postgres
6
- command: -p 55433
7
- image: postgres:11.4
8
- ports:
9
- - "55433:55433"
10
- volumes:
11
- - vorpal_postgres_volume:/var/lib/postgresql/data
12
- environment:
13
- POSTGRES_USER: vorpal
14
- POSTGRES_PASSWORD: pass
15
- POSTGRES_DB: vorpal_development
16
- restart: unless-stopped
17
-
18
- volumes:
19
- vorpal_postgres_volume:
@@ -1,11 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- ruby ">= 2.5.7"
6
-
7
- gem "activerecord", "~> 5.1.0"
8
- gem "pg", "~> 0.18.0"
9
- gem "activerecord-import", "= 0.13.0"
10
-
11
- gemspec path: "../"
@@ -1,101 +0,0 @@
1
- PATH
2
- remote: ..
3
- specs:
4
- vorpal (1.0.3)
5
- activesupport
6
- equalizer
7
- simple_serializer (~> 1.0)
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- activemodel (5.1.7)
13
- activesupport (= 5.1.7)
14
- activerecord (5.1.7)
15
- activemodel (= 5.1.7)
16
- activesupport (= 5.1.7)
17
- arel (~> 8.0)
18
- activerecord-import (0.13.0)
19
- activerecord (>= 3.0)
20
- activesupport (5.1.7)
21
- concurrent-ruby (~> 1.0, >= 1.0.2)
22
- i18n (>= 0.7, < 2)
23
- minitest (~> 5.1)
24
- tzinfo (~> 1.1)
25
- appraisal (2.2.0)
26
- bundler
27
- rake
28
- thor (>= 0.14.0)
29
- arel (8.0.0)
30
- axiom-types (0.1.1)
31
- descendants_tracker (~> 0.0.4)
32
- ice_nine (~> 0.11.0)
33
- thread_safe (~> 0.3, >= 0.3.1)
34
- codecov (0.1.16)
35
- json
36
- simplecov
37
- url
38
- coercible (1.0.0)
39
- descendants_tracker (~> 0.0.1)
40
- concurrent-ruby (1.1.5)
41
- descendants_tracker (0.0.4)
42
- thread_safe (~> 0.3, >= 0.3.1)
43
- diff-lcs (1.3)
44
- docile (1.3.2)
45
- equalizer (0.0.11)
46
- i18n (1.8.2)
47
- concurrent-ruby (~> 1.0)
48
- ice_nine (0.11.2)
49
- json (2.3.0)
50
- minitest (5.14.0)
51
- pg (0.18.4)
52
- rake (10.5.0)
53
- rspec (3.8.0)
54
- rspec-core (~> 3.8.0)
55
- rspec-expectations (~> 3.8.0)
56
- rspec-mocks (~> 3.8.0)
57
- rspec-core (3.8.0)
58
- rspec-support (~> 3.8.0)
59
- rspec-expectations (3.8.1)
60
- diff-lcs (>= 1.2.0, < 2.0)
61
- rspec-support (~> 3.8.0)
62
- rspec-mocks (3.8.0)
63
- diff-lcs (>= 1.2.0, < 2.0)
64
- rspec-support (~> 3.8.0)
65
- rspec-support (3.8.0)
66
- simple_serializer (1.0.2)
67
- simplecov (0.17.1)
68
- docile (~> 1.1)
69
- json (>= 1.8, < 3)
70
- simplecov-html (~> 0.10.0)
71
- simplecov-html (0.10.2)
72
- thor (0.20.0)
73
- thread_safe (0.3.6)
74
- tzinfo (1.2.6)
75
- thread_safe (~> 0.1)
76
- url (0.3.2)
77
- virtus (1.0.5)
78
- axiom-types (~> 0.1)
79
- coercible (~> 1.0)
80
- descendants_tracker (~> 0.0, >= 0.0.3)
81
- equalizer (~> 0.0, >= 0.0.9)
82
-
83
- PLATFORMS
84
- ruby
85
-
86
- DEPENDENCIES
87
- activerecord (~> 5.1.0)
88
- activerecord-import (= 0.13.0)
89
- appraisal (~> 2.2)
90
- codecov
91
- pg (~> 0.18.0)
92
- rake (~> 10)
93
- rspec (~> 3.0)
94
- virtus (~> 1.0)
95
- vorpal!
96
-
97
- RUBY VERSION
98
- ruby 2.6.3p62
99
-
100
- BUNDLED WITH
101
- 1.17.2
@@ -1,11 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- ruby ">= 2.5.7"
6
-
7
- gem "activerecord", "~> 5.2.0"
8
- gem "pg", "~> 0.18.0"
9
- gem "activerecord-import", "= 0.13.0"
10
-
11
- gemspec path: "../"
@@ -1,101 +0,0 @@
1
- PATH
2
- remote: ..
3
- specs:
4
- vorpal (1.0.3)
5
- activesupport
6
- equalizer
7
- simple_serializer (~> 1.0)
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- activemodel (5.2.4.1)
13
- activesupport (= 5.2.4.1)
14
- activerecord (5.2.4.1)
15
- activemodel (= 5.2.4.1)
16
- activesupport (= 5.2.4.1)
17
- arel (>= 9.0)
18
- activerecord-import (0.13.0)
19
- activerecord (>= 3.0)
20
- activesupport (5.2.4.1)
21
- concurrent-ruby (~> 1.0, >= 1.0.2)
22
- i18n (>= 0.7, < 2)
23
- minitest (~> 5.1)
24
- tzinfo (~> 1.1)
25
- appraisal (2.2.0)
26
- bundler
27
- rake
28
- thor (>= 0.14.0)
29
- arel (9.0.0)
30
- axiom-types (0.1.1)
31
- descendants_tracker (~> 0.0.4)
32
- ice_nine (~> 0.11.0)
33
- thread_safe (~> 0.3, >= 0.3.1)
34
- codecov (0.1.16)
35
- json
36
- simplecov
37
- url
38
- coercible (1.0.0)
39
- descendants_tracker (~> 0.0.1)
40
- concurrent-ruby (1.1.5)
41
- descendants_tracker (0.0.4)
42
- thread_safe (~> 0.3, >= 0.3.1)
43
- diff-lcs (1.3)
44
- docile (1.3.2)
45
- equalizer (0.0.11)
46
- i18n (1.8.2)
47
- concurrent-ruby (~> 1.0)
48
- ice_nine (0.11.2)
49
- json (2.3.0)
50
- minitest (5.14.0)
51
- pg (0.18.4)
52
- rake (10.5.0)
53
- rspec (3.8.0)
54
- rspec-core (~> 3.8.0)
55
- rspec-expectations (~> 3.8.0)
56
- rspec-mocks (~> 3.8.0)
57
- rspec-core (3.8.0)
58
- rspec-support (~> 3.8.0)
59
- rspec-expectations (3.8.1)
60
- diff-lcs (>= 1.2.0, < 2.0)
61
- rspec-support (~> 3.8.0)
62
- rspec-mocks (3.8.0)
63
- diff-lcs (>= 1.2.0, < 2.0)
64
- rspec-support (~> 3.8.0)
65
- rspec-support (3.8.0)
66
- simple_serializer (1.0.2)
67
- simplecov (0.17.1)
68
- docile (~> 1.1)
69
- json (>= 1.8, < 3)
70
- simplecov-html (~> 0.10.0)
71
- simplecov-html (0.10.2)
72
- thor (0.20.0)
73
- thread_safe (0.3.6)
74
- tzinfo (1.2.6)
75
- thread_safe (~> 0.1)
76
- url (0.3.2)
77
- virtus (1.0.5)
78
- axiom-types (~> 0.1)
79
- coercible (~> 1.0)
80
- descendants_tracker (~> 0.0, >= 0.0.3)
81
- equalizer (~> 0.0, >= 0.0.9)
82
-
83
- PLATFORMS
84
- ruby
85
-
86
- DEPENDENCIES
87
- activerecord (~> 5.2.0)
88
- activerecord-import (= 0.13.0)
89
- appraisal (~> 2.2)
90
- codecov
91
- pg (~> 0.18.0)
92
- rake (~> 10)
93
- rspec (~> 3.0)
94
- virtus (~> 1.0)
95
- vorpal!
96
-
97
- RUBY VERSION
98
- ruby 2.6.3p62
99
-
100
- BUNDLED WITH
101
- 1.17.2
@@ -1,9 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- ruby ">= 2.7.0"
6
-
7
- gem "activerecord", "~> 6.0.0"
8
-
9
- gemspec path: "../"
@@ -1,101 +0,0 @@
1
- PATH
2
- remote: ..
3
- specs:
4
- vorpal (1.0.3)
5
- activesupport
6
- equalizer
7
- simple_serializer (~> 1.0)
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- activemodel (6.0.2.1)
13
- activesupport (= 6.0.2.1)
14
- activerecord (6.0.2.1)
15
- activemodel (= 6.0.2.1)
16
- activesupport (= 6.0.2.1)
17
- activerecord-import (1.0.4)
18
- activerecord (>= 3.2)
19
- activesupport (6.0.2.1)
20
- concurrent-ruby (~> 1.0, >= 1.0.2)
21
- i18n (>= 0.7, < 2)
22
- minitest (~> 5.1)
23
- tzinfo (~> 1.1)
24
- zeitwerk (~> 2.2)
25
- appraisal (2.2.0)
26
- bundler
27
- rake
28
- thor (>= 0.14.0)
29
- axiom-types (0.1.1)
30
- descendants_tracker (~> 0.0.4)
31
- ice_nine (~> 0.11.0)
32
- thread_safe (~> 0.3, >= 0.3.1)
33
- codecov (0.1.16)
34
- json
35
- simplecov
36
- url
37
- coercible (1.0.0)
38
- descendants_tracker (~> 0.0.1)
39
- concurrent-ruby (1.1.5)
40
- descendants_tracker (0.0.4)
41
- thread_safe (~> 0.3, >= 0.3.1)
42
- diff-lcs (1.3)
43
- docile (1.3.2)
44
- equalizer (0.0.11)
45
- i18n (1.8.2)
46
- concurrent-ruby (~> 1.0)
47
- ice_nine (0.11.2)
48
- json (2.3.0)
49
- minitest (5.14.0)
50
- pg (1.2.2)
51
- rake (10.5.0)
52
- rspec (3.9.0)
53
- rspec-core (~> 3.9.0)
54
- rspec-expectations (~> 3.9.0)
55
- rspec-mocks (~> 3.9.0)
56
- rspec-core (3.9.1)
57
- rspec-support (~> 3.9.1)
58
- rspec-expectations (3.9.0)
59
- diff-lcs (>= 1.2.0, < 2.0)
60
- rspec-support (~> 3.9.0)
61
- rspec-mocks (3.9.1)
62
- diff-lcs (>= 1.2.0, < 2.0)
63
- rspec-support (~> 3.9.0)
64
- rspec-support (3.9.2)
65
- simple_serializer (1.0.2)
66
- simplecov (0.17.1)
67
- docile (~> 1.1)
68
- json (>= 1.8, < 3)
69
- simplecov-html (~> 0.10.0)
70
- simplecov-html (0.10.2)
71
- thor (1.0.1)
72
- thread_safe (0.3.6)
73
- tzinfo (1.2.6)
74
- thread_safe (~> 0.1)
75
- url (0.3.2)
76
- virtus (1.0.5)
77
- axiom-types (~> 0.1)
78
- coercible (~> 1.0)
79
- descendants_tracker (~> 0.0, >= 0.0.3)
80
- equalizer (~> 0.0, >= 0.0.9)
81
- zeitwerk (2.2.2)
82
-
83
- PLATFORMS
84
- ruby
85
-
86
- DEPENDENCIES
87
- activerecord (~> 6.0.0)
88
- activerecord-import
89
- appraisal (~> 2.2)
90
- codecov
91
- pg
92
- rake (~> 10)
93
- rspec (~> 3.0)
94
- virtus (~> 1.0)
95
- vorpal!
96
-
97
- RUBY VERSION
98
- ruby 2.7.0p0
99
-
100
- BUNDLED WITH
101
- 2.1.4
@@ -1,910 +0,0 @@
1
- require 'integration_spec_helper'
2
- require 'vorpal'
3
- require 'virtus'
4
-
5
- describe 'AggregateMapper' do
6
-
7
- # for testing polymorphic associations
8
- class Bug
9
- include Virtus.model
10
-
11
- attribute :id, Integer
12
- attribute :name, String
13
- attribute :lives_on, Object
14
- end
15
-
16
- class Tree; end
17
-
18
- class Trunk
19
- include Virtus.model
20
-
21
- attribute :id, Integer
22
- attribute :length, Decimal
23
- attribute :bugs, Array[Bug]
24
- attribute :tree, Tree
25
- end
26
-
27
- class Branch
28
- include Virtus.model
29
-
30
- attribute :id, Integer
31
- attribute :length, Decimal
32
- attribute :tree, Tree
33
- attribute :branches, Array[Branch]
34
- attribute :bugs, Array[Bug]
35
- end
36
-
37
- class Fissure < ActiveRecord::Base; end
38
- class Swamp < ActiveRecord::Base; end
39
-
40
- class Tree
41
- include Virtus.model
42
-
43
- attribute :id, Integer
44
- attribute :name, String
45
- attribute :trunk, Trunk
46
- attribute :environment, Object
47
- attribute :fissures, Array[Fissure]
48
- attribute :branches, Array[Branch]
49
- end
50
-
51
- before(:all) do
52
- define_table('branches', {length: :decimal, tree_id: :integer, branch_id: :integer}, false)
53
- define_table('bugs', {name: :text, lives_on_id: :integer, lives_on_type: :string}, false)
54
- define_table('fissures', {length: :decimal, tree_id: :integer}, false)
55
- define_table('trees', {name: :text, trunk_id: :integer, environment_id: :integer, environment_type: :string}, false)
56
- define_table('trunks', {length: :decimal}, false)
57
- define_table('swamps', {}, false)
58
- end
59
-
60
- describe 'new records' do
61
- it 'saves attributes' do
62
- test_mapper = configure
63
-
64
- tree = Tree.new(name: 'backyard tree')
65
- test_mapper.persist(tree)
66
-
67
- tree_db = db_class_for(Tree, test_mapper).first
68
- expect(tree_db.name).to eq 'backyard tree'
69
- end
70
-
71
- it 'sets the id when first saved' do
72
- test_mapper = configure
73
-
74
- tree = Tree.new()
75
- test_mapper.persist(tree)
76
-
77
- expect(tree.id).to_not be nil
78
-
79
- tree_db = db_class_for(Tree, test_mapper).first
80
- expect(tree_db.id).to eq tree.id
81
- end
82
-
83
- it 'saves AR::Base objects' do
84
- test_mapper = configure
85
-
86
- fissure = Fissure.new(length: 21)
87
- tree = Tree.new(fissures: [fissure])
88
-
89
- test_mapper.persist(tree)
90
-
91
- expect(Fissure.first.length).to eq 21
92
- end
93
- end
94
-
95
- describe 'on error' do
96
- it 'nils ids of new objects' do
97
- db_driver = Vorpal::Driver::Postgresql.new
98
- test_mapper = configure(db_driver: db_driver)
99
-
100
- tree_db = db_class_for(Tree, test_mapper).create!
101
-
102
- expect(db_driver).to receive(:update).and_raise('not so good')
103
-
104
- fissure = Fissure.new
105
- tree = Tree.new(id: tree_db.id, fissures: [fissure])
106
-
107
- expect {
108
- test_mapper.persist(tree)
109
- }.to raise_error(Exception)
110
-
111
- expect(fissure.id).to eq nil
112
- expect(tree.id).to_not eq nil
113
- end
114
- end
115
-
116
- describe 'existing records' do
117
- it 'updates attributes' do
118
- test_mapper = configure
119
-
120
- tree = Tree.new(name: 'little tree')
121
- test_mapper.persist(tree)
122
-
123
- tree.name = 'big tree'
124
- test_mapper.persist(tree)
125
-
126
- tree_db = db_class_for(Tree, test_mapper).first
127
- expect(tree_db.name).to eq 'big tree'
128
- end
129
-
130
- it 'does not change the id on update' do
131
- test_mapper = configure
132
-
133
- tree = Tree.new
134
- test_mapper.persist(tree)
135
-
136
- original_id = tree.id
137
-
138
- tree.name = 'change it'
139
- test_mapper.persist(tree)
140
-
141
- expect(tree.id).to eq original_id
142
- end
143
-
144
- it 'does not create additional records' do
145
- test_mapper = configure
146
-
147
- tree = Tree.new
148
- test_mapper.persist(tree)
149
-
150
- tree.name = 'change it'
151
- test_mapper.persist(tree)
152
-
153
- expect(db_class_for(Tree, test_mapper).count).to eq 1
154
- end
155
-
156
- it 'removes orphans' do
157
- test_mapper = configure
158
-
159
- tree_db = db_class_for(Tree, test_mapper).create!
160
- db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
161
-
162
- tree = Tree.new(id: tree_db.id, branches: [])
163
-
164
- test_mapper.persist(tree)
165
-
166
- expect(db_class_for(Branch, test_mapper).count).to eq 0
167
- end
168
-
169
- it 'does not remove orphans from unowned associations' do
170
- test_mapper = configure_unowned
171
-
172
- tree_db = db_class_for(Tree, test_mapper).create!
173
- db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
174
-
175
- tree = Tree.new(id: tree_db.id, branches: [])
176
-
177
- test_mapper.persist(tree)
178
-
179
- expect(db_class_for(Branch, test_mapper).count).to eq 1
180
- end
181
- end
182
-
183
- it 'copies attributes to domain' do
184
- test_mapper = configure
185
-
186
- tree_db = db_class_for(Tree, test_mapper).create! name: 'tree name'
187
- tree = test_mapper.load_one(tree_db)
188
-
189
- expect(tree.id).to eq tree_db.id
190
- expect(tree.name).to eq 'tree name'
191
- end
192
-
193
- it 'hydrates ActiveRecord::Base associations' do
194
- test_mapper = configure
195
-
196
- tree_db = db_class_for(Tree, test_mapper).create!
197
- Fissure.create! length: 21, tree_id: tree_db.id
198
-
199
- tree = test_mapper.load_one(tree_db)
200
-
201
- expect(tree.fissures.first.length).to eq 21
202
- end
203
-
204
- describe 'cycles' do
205
- it 'persists' do
206
- test_mapper = configure_with_cycle
207
-
208
- tree = Tree.new
209
- long_branch = Branch.new(length: 100, tree: tree)
210
- tree.branches << long_branch
211
-
212
- test_mapper.persist(tree)
213
-
214
- expect(db_class_for(Tree, test_mapper).count).to eq 1
215
- end
216
-
217
- it 'hydrates' do
218
- test_mapper = configure_with_cycle
219
-
220
- tree_db = db_class_for(Tree, test_mapper).create!
221
- db_class_for(Branch, test_mapper).create!(length: 50, tree_id: tree_db.id)
222
-
223
- tree = test_mapper.load_one(tree_db)
224
-
225
- expect(tree).to be tree.branches.first.tree
226
- end
227
- end
228
-
229
- describe 'recursive associations' do
230
- it 'persists' do
231
- test_mapper = configure_recursive
232
-
233
- tree = Tree.new
234
- long_branch = Branch.new(length: 100, tree: tree)
235
- tree.branches << long_branch
236
- short_branch = Branch.new(length: 50, tree: tree)
237
- long_branch.branches << short_branch
238
-
239
- test_mapper.persist(tree)
240
-
241
- expect(db_class_for(Branch, test_mapper).count).to eq 2
242
- end
243
-
244
- it 'hydrates' do
245
- test_mapper = configure_recursive
246
-
247
- tree_db = db_class_for(Tree, test_mapper).create!
248
- long_branch = db_class_for(Branch, test_mapper).create!(length: 100, tree_id: tree_db.id)
249
- db_class_for(Branch, test_mapper).create!(length: 50, branch_id: long_branch.id)
250
-
251
- tree = test_mapper.load_one(tree_db)
252
-
253
- expect(tree.branches.first.branches.first.length).to eq 50
254
- end
255
- end
256
-
257
- describe 'belongs_to associations' do
258
- it 'saves attributes' do
259
- test_mapper = configure
260
- trunk = Trunk.new(length: 12)
261
- tree = Tree.new(trunk: trunk)
262
-
263
- test_mapper.persist(tree)
264
-
265
- trunk_db = db_class_for(Trunk, test_mapper).first
266
- expect(trunk_db.length).to eq 12
267
- end
268
-
269
- it 'saves foreign keys' do
270
- test_mapper = configure
271
- trunk = Trunk.new
272
- tree = Tree.new(trunk: trunk)
273
-
274
- test_mapper.persist(tree)
275
-
276
- tree_db = db_class_for(Tree, test_mapper).first
277
- expect(tree_db.trunk_id).to eq trunk.id
278
- end
279
-
280
- it 'updating does not create additional rows' do
281
- test_mapper = configure
282
- trunk = Trunk.new
283
- tree = Tree.new(trunk: trunk)
284
-
285
- test_mapper.persist(tree)
286
-
287
- trunk.length = 21
288
-
289
- expect{ test_mapper.persist(tree) }.to_not change{ db_class_for(Trunk, test_mapper).count }
290
- end
291
-
292
- it 'only saves entities that are owned' do
293
- test_mapper = configure_unowned
294
-
295
- trunk = Trunk.new
296
- tree = Tree.new(trunk: trunk)
297
-
298
- test_mapper.persist(tree)
299
-
300
- expect(db_class_for(Trunk, test_mapper).count).to eq 0
301
- end
302
-
303
- it 'hydrates' do
304
- test_mapper = configure
305
- trunk_db = db_class_for(Trunk, test_mapper).create!(length: 21)
306
- tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
307
-
308
- new_tree = test_mapper.load_one(tree_db)
309
- expect(new_tree.trunk.length).to eq 21
310
- end
311
- end
312
-
313
- describe 'has_many associations' do
314
- it 'saves' do
315
- test_mapper = configure
316
- tree = Tree.new
317
- tree.branches << Branch.new(length: 100)
318
- tree.branches << Branch.new(length: 3)
319
-
320
- test_mapper.persist(tree)
321
-
322
- branches = db_class_for(Branch, test_mapper).all
323
- expect(branches.size).to eq 2
324
- expect(branches.first.length).to eq 100
325
- expect(branches.second.length).to eq 3
326
- end
327
-
328
- it 'saves foreign keys' do
329
- test_mapper = configure
330
- tree = Tree.new
331
- tree.branches << Branch.new(length: 100)
332
-
333
- test_mapper.persist(tree)
334
-
335
- branches = db_class_for(Branch, test_mapper).all
336
- expect(branches.first.tree_id).to eq tree.id
337
- end
338
-
339
- it 'updates' do
340
- test_mapper = configure
341
- tree = Tree.new
342
- long_branch = Branch.new(length: 100)
343
- tree.branches << long_branch
344
-
345
- test_mapper.persist(tree)
346
-
347
- long_branch.length = 120
348
-
349
- test_mapper.persist(tree)
350
-
351
- branches = db_class_for(Branch, test_mapper).all
352
- expect(branches.first.length).to eq 120
353
- end
354
-
355
- it 'only saves entities that are owned' do
356
- test_mapper = configure_unowned
357
-
358
- tree = Tree.new
359
- long_branch = Branch.new(length: 100)
360
- tree.branches << long_branch
361
-
362
- test_mapper.persist(tree)
363
-
364
- expect(db_class_for(Branch, test_mapper).count).to eq 0
365
- end
366
-
367
- it 'hydrates' do
368
- test_mapper = configure
369
-
370
- tree_db = db_class_for(Tree, test_mapper).create!
371
- db_class_for(Branch, test_mapper).create!(length: 50, tree_id: tree_db.id)
372
-
373
- tree = test_mapper.load_one(tree_db)
374
-
375
- expect(tree.branches.first.length).to eq 50
376
- end
377
- end
378
-
379
- describe 'has_one associations' do
380
- it 'saves' do
381
- test_mapper = configure_has_one
382
- tree = Tree.new(name: 'big tree')
383
- trunk = Trunk.new(tree: tree)
384
-
385
- test_mapper.persist(trunk)
386
-
387
- expect(db_class_for(Tree, test_mapper).first.name).to eq 'big tree'
388
- end
389
-
390
- it 'saves foreign keys' do
391
- test_mapper = configure_has_one
392
- tree = Tree.new(name: 'big tree')
393
- trunk = Trunk.new(tree: tree)
394
-
395
- test_mapper.persist(trunk)
396
-
397
- expect(db_class_for(Tree, test_mapper).first.trunk_id).to eq trunk.id
398
- end
399
-
400
- it 'only saves entities that are owned' do
401
- test_mapper = configure_unowned_has_one
402
- tree = Tree.new
403
- trunk = Trunk.new(tree: tree)
404
-
405
- test_mapper.persist(trunk)
406
-
407
- expect(db_class_for(Tree, test_mapper).count).to eq 0
408
- end
409
-
410
- it 'hydrates' do
411
- test_mapper = configure_has_one
412
-
413
- trunk_db = db_class_for(Trunk, test_mapper).create!
414
- db_class_for(Tree, test_mapper).create!(name: 'big tree', trunk_id: trunk_db.id)
415
-
416
- trunk = test_mapper.load_one(trunk_db)
417
-
418
- expect(trunk.tree.name).to eq 'big tree'
419
- end
420
- end
421
-
422
- describe 'polymorphic associations' do
423
- it 'saves with has_manys' do
424
- test_mapper = configure_polymorphic_has_many
425
- trunk = Trunk.new
426
- branch = Branch.new
427
- tree = Tree.new(trunk: trunk, branches: [branch])
428
-
429
- trunk_bug = Bug.new
430
- trunk.bugs << trunk_bug
431
- branch_bug = Bug.new
432
- branch.bugs << branch_bug
433
-
434
- test_mapper.persist(tree)
435
-
436
- expect(db_class_for(Bug, test_mapper).find(trunk_bug.id).lives_on_type).to eq Trunk.name
437
- expect(db_class_for(Bug, test_mapper).find(branch_bug.id).lives_on_type).to eq Branch.name
438
- end
439
-
440
- it 'restores with has_manys' do
441
- test_mapper = configure_polymorphic_has_many
442
-
443
- trunk_db = db_class_for(Trunk, test_mapper).create!
444
- tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
445
- db_class_for(Bug, test_mapper).create!(name: 'trunk bug', lives_on_id: trunk_db.id, lives_on_type: Trunk.name)
446
- db_class_for(Bug, test_mapper).create!(name: 'not a trunk bug!', lives_on_id: trunk_db.id, lives_on_type: 'some other table')
447
-
448
- tree = test_mapper.load_one(tree_db)
449
-
450
- expect(tree.trunk.bugs.map(&:name)).to eq ['trunk bug']
451
- end
452
-
453
- it 'saves with belongs_tos' do
454
- test_mapper = configure_polymorphic_belongs_to
455
-
456
- trunk_bug = Bug.new(lives_on: Trunk.new)
457
- branch_bug = Bug.new(lives_on: Branch.new)
458
-
459
- test_mapper.persist([trunk_bug, branch_bug])
460
-
461
- expect(db_class_for(Bug, test_mapper).find(trunk_bug.id).lives_on_type).to eq Trunk.name
462
- expect(db_class_for(Bug, test_mapper).find(branch_bug.id).lives_on_type).to eq Branch.name
463
- end
464
-
465
- it 'saves associations to unowned entities via belongs_to' do
466
- test_mapper = configure_unowned_polymorphic_belongs_to
467
- trunk = Trunk.new
468
-
469
- trunk_bug = Bug.new(lives_on: trunk)
470
-
471
- test_mapper.persist(trunk_bug)
472
-
473
- expect(db_class_for(Bug, test_mapper).find(trunk_bug.id).lives_on_type).to eq Trunk.name
474
- end
475
-
476
- it 'restores with belongs_tos' do
477
- test_mapper = configure_polymorphic_belongs_to
478
-
479
- # makes sure that we are using the fk_type to discriminate against
480
- # two entities with the same primary key value
481
- trunk_db = db_class_for(Trunk, test_mapper).new(length: 99)
482
- trunk_db.id = 99
483
- trunk_db.save!
484
- trunk_bug_db = db_class_for(Bug, test_mapper).create!(lives_on_id: trunk_db.id, lives_on_type: Trunk.name)
485
- branch_db = db_class_for(Branch, test_mapper).new(length: 5)
486
- branch_db.id = 99
487
- branch_db.save!
488
- branch_bug_db = db_class_for(Bug, test_mapper).create!(lives_on_id: branch_db.id, lives_on_type: Branch.name)
489
-
490
- trunk_bug, branch_bug = test_mapper.load_many([trunk_bug_db, branch_bug_db])
491
-
492
- expect(trunk_bug.lives_on.length).to eq 99
493
- expect(branch_bug.lives_on.length).to eq 5
494
- end
495
-
496
- it 'restores active record objects' do
497
- test_mapper = configure_ar_polymorphic_belongs_to
498
-
499
- swamp = Swamp.create!
500
- tree_db = db_class_for(Tree, test_mapper).create!(environment_id: swamp.id, environment_type: Swamp.name)
501
-
502
- tree = test_mapper.load_one(tree_db)
503
-
504
- expect(tree.environment).to eq swamp
505
- end
506
- end
507
-
508
- describe 'arel' do
509
- it 'loads many' do
510
- test_mapper = configure
511
-
512
- db_class_for(Tree, test_mapper).create!
513
- tree_db = db_class_for(Tree, test_mapper).create!
514
-
515
- trees = test_mapper.query.where(id: tree_db.id).load_many
516
-
517
- expect(trees.map(&:id)).to eq [tree_db.id]
518
- end
519
-
520
- it 'loads one' do
521
- test_mapper = configure
522
-
523
- db_class_for(Tree, test_mapper).create!
524
- tree_db = db_class_for(Tree, test_mapper).create!
525
-
526
- trees = test_mapper.query.where(id: tree_db.id).load_one
527
-
528
- expect(trees.id).to eq tree_db.id
529
- end
530
- end
531
-
532
- describe 'load_many' do
533
- it 'maps given db objects' do
534
- test_mapper = configure
535
-
536
- db_class_for(Tree, test_mapper).create!
537
- tree_db = db_class_for(Tree, test_mapper).create!
538
-
539
- trees = test_mapper.load_many([tree_db])
540
-
541
- expect(trees.map(&:id)).to eq [tree_db.id]
542
- end
543
-
544
- it 'only returns roots' do
545
- test_mapper = configure
546
-
547
- db_class_for(Tree, test_mapper).create!
548
- tree_db = db_class_for(Tree, test_mapper).create!
549
- db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
550
-
551
- trees = test_mapper.load_many([tree_db])
552
-
553
- expect(trees.map(&:id)).to eq [tree_db.id]
554
- end
555
- end
556
-
557
- describe 'destroy' do
558
- it 'removes the entity from the database' do
559
- test_mapper = configure
560
-
561
- tree_db = db_class_for(Tree, test_mapper).create!
562
-
563
- test_mapper.destroy([Tree.new(id: tree_db.id)])
564
-
565
- expect(db_class_for(Tree, test_mapper).count).to eq 0
566
- end
567
-
568
- it 'removes has many children from the database' do
569
- test_mapper = configure
570
-
571
- tree_db = db_class_for(Tree, test_mapper).create!
572
- db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
573
-
574
- test_mapper.destroy(Tree.new(id: tree_db.id))
575
-
576
- expect(db_class_for(Branch, test_mapper).count).to eq 0
577
- end
578
-
579
- it 'removes belongs to children from the database' do
580
- test_mapper = configure
581
-
582
- trunk_db = db_class_for(Trunk, test_mapper).create!
583
- tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
584
-
585
- test_mapper.destroy(Tree.new(id: tree_db.id))
586
-
587
- expect(db_class_for(Trunk, test_mapper).count).to eq 0
588
- end
589
-
590
- it 'removes AR children from the database' do
591
- test_mapper = configure
592
-
593
- tree_db = db_class_for(Tree, test_mapper).create!
594
- Fissure.create!(tree_id: tree_db.id)
595
-
596
- test_mapper.destroy(Tree.new(id: tree_db.id))
597
-
598
- expect(Fissure.count).to eq 0
599
- end
600
-
601
- it 'leaves unowned belongs to children in the database' do
602
- test_mapper = configure_unowned
603
-
604
- trunk_db = db_class_for(Trunk, test_mapper).create!
605
- tree_db = db_class_for(Tree, test_mapper).create!(trunk_id: trunk_db.id)
606
-
607
- test_mapper.destroy(Tree.new(id: tree_db.id))
608
-
609
- expect(db_class_for(Trunk, test_mapper).count).to eq 1
610
- end
611
-
612
- it 'leaves unowned has many children in the database' do
613
- test_mapper = configure_unowned
614
-
615
- tree_db = db_class_for(Tree, test_mapper).create!
616
- db_class_for(Branch, test_mapper).create!(tree_id: tree_db.id)
617
-
618
- test_mapper.destroy(Tree.new(id: tree_db.id))
619
-
620
- expect(db_class_for(Branch, test_mapper).count).to eq 1
621
- end
622
- end
623
-
624
- describe 'destroy_by_id' do
625
- it 'removes the entity from the database' do
626
- test_mapper = configure
627
-
628
- tree_db = db_class_for(Tree, test_mapper).create!
629
-
630
- test_mapper.destroy_by_id([tree_db.id])
631
-
632
- expect(db_class_for(Tree, test_mapper).count).to eq 0
633
- end
634
- end
635
-
636
- describe 'non-existent values' do
637
- it 'load_many returns an empty array when given an empty array' do
638
- test_mapper = configure
639
-
640
- results = test_mapper.load_many([])
641
- expect(results).to eq []
642
- end
643
-
644
- it 'load_many throws an exception when given a nil db_object' do
645
- test_mapper = configure
646
-
647
- expect {
648
- test_mapper.load_many([nil])
649
- }.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
650
- end
651
-
652
- it 'load_one returns nil when given nil' do
653
- test_mapper = configure
654
-
655
- result = test_mapper.load_one(nil)
656
- expect(result).to eq nil
657
- end
658
-
659
- it 'persist ignores empty arrays' do
660
- test_mapper = configure
661
-
662
- results = test_mapper.persist([])
663
- expect(results).to eq []
664
- end
665
-
666
- it 'persist throws an exception when given a collection with a nil root' do
667
- test_mapper = configure
668
- expect {
669
- test_mapper.persist([nil])
670
- }.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
671
- end
672
-
673
- it 'persist throws an exception when given a nil root' do
674
- test_mapper = configure
675
- expect {
676
- test_mapper.persist(nil)
677
- }.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
678
- end
679
-
680
- it 'destroy ignores empty arrays' do
681
- test_mapper = configure
682
-
683
- results = test_mapper.destroy([])
684
- expect(results).to eq []
685
- end
686
-
687
- it 'destroy throws an exception when given a nil root' do
688
- test_mapper = configure
689
-
690
- expect {
691
- test_mapper.destroy(nil)
692
- }.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
693
- end
694
-
695
- it 'destroy throws an exception when given a collection with a nil root' do
696
- test_mapper = configure
697
-
698
- expect {
699
- test_mapper.destroy([nil])
700
- }.to raise_error(Vorpal::InvalidAggregateRoot, "Nil aggregate roots are not allowed.")
701
- end
702
-
703
- it 'destroy_by_id ignores empty arrays' do
704
- test_mapper = configure
705
-
706
- results = test_mapper.destroy_by_id([])
707
- expect(results).to eq []
708
- end
709
-
710
- it 'destroy_by_id ignores ids that do not exist' do
711
- test_mapper = configure
712
-
713
- test_mapper.destroy_by_id([99])
714
- end
715
-
716
- it 'destroy_by_id throws an exception when given a collection with a nil id' do
717
- test_mapper = configure
718
-
719
- expect {
720
- test_mapper.destroy_by_id([nil])
721
- }.to raise_error(Vorpal::InvalidPrimaryKeyValue, "Nil primary key values are not allowed.")
722
- end
723
-
724
- it 'destroy_by_id throws an exception when given a nil id' do
725
- test_mapper = configure
726
-
727
- expect {
728
- test_mapper.destroy_by_id(nil)
729
- }.to raise_error(Vorpal::InvalidPrimaryKeyValue, "Nil primary key values are not allowed.")
730
- end
731
- end
732
-
733
- private
734
-
735
- def db_class_for(clazz, mapper)
736
- mapper.engine.mapper_for(clazz).db_class
737
- end
738
-
739
- def configure_polymorphic_has_many
740
- engine = Vorpal.define do
741
- map Tree do
742
- attributes :name
743
- has_many :branches
744
- belongs_to :trunk
745
- end
746
-
747
- map Trunk do
748
- attributes :length
749
- has_many :bugs, fk: :lives_on_id, fk_type: :lives_on_type
750
- end
751
-
752
- map Branch do
753
- attributes :length
754
- has_many :bugs, fk: :lives_on_id, fk_type: :lives_on_type
755
- end
756
-
757
- map Bug do
758
- attributes :name
759
- end
760
- end
761
- engine.mapper_for(Tree)
762
- end
763
-
764
- def configure_polymorphic_belongs_to
765
- engine = Vorpal.define do
766
- map Bug do
767
- attributes :name
768
- belongs_to :lives_on, fk: :lives_on_id, fk_type: :lives_on_type, child_classes: [Trunk, Branch]
769
- end
770
-
771
- map Trunk do
772
- attributes :length
773
- end
774
-
775
- map Branch do
776
- attributes :length
777
- end
778
- end
779
- engine.mapper_for(Bug)
780
- end
781
-
782
- def configure_ar_polymorphic_belongs_to
783
- engine = Vorpal.define do
784
- map Tree do
785
- attributes :name
786
- belongs_to :environment, owned: false, fk: :environment_id, fk_type: :environment_type, child_class: Swamp
787
- end
788
-
789
- map Swamp, to: Swamp
790
- end
791
- engine.mapper_for(Tree)
792
- end
793
-
794
- def configure_unowned_polymorphic_belongs_to
795
- engine = Vorpal.define do
796
- map Bug do
797
- attributes :name
798
- belongs_to :lives_on, owned: false, fk: :lives_on_id, fk_type: :lives_on_type, child_classes: [Trunk, Branch]
799
- end
800
-
801
- map Trunk do
802
- attributes :length
803
- end
804
-
805
- map Branch do
806
- attributes :length
807
- end
808
- end
809
- engine.mapper_for(Bug)
810
- end
811
-
812
- def configure_unowned
813
- engine = Vorpal.define do
814
- map Tree do
815
- attributes :name
816
- has_many :branches, owned: false
817
- belongs_to :trunk, owned: false
818
- end
819
-
820
- map Trunk do
821
- attributes :length
822
- end
823
-
824
- map Branch do
825
- attributes :length
826
- end
827
- end
828
- engine.mapper_for(Tree)
829
- end
830
-
831
- def configure_recursive
832
- engine = Vorpal.define do
833
- map Branch do
834
- attributes :length
835
- has_many :branches
836
- end
837
-
838
- map Tree do
839
- attributes :name
840
- has_many :branches
841
- end
842
- end
843
- engine.mapper_for(Tree)
844
- end
845
-
846
- def configure_with_cycle
847
- engine = Vorpal.define do
848
- map Branch do
849
- attributes :length
850
- belongs_to :tree
851
- end
852
-
853
- map Tree do
854
- attributes :name
855
- has_many :branches
856
- end
857
- end
858
- engine.mapper_for(Tree)
859
- end
860
-
861
- def configure(options={})
862
- engine = Vorpal.define(options) do
863
- map Tree do
864
- attributes :name
865
- belongs_to :trunk
866
- has_many :fissures
867
- has_many :branches
868
- end
869
-
870
- map Trunk do
871
- attributes :length
872
- end
873
-
874
- map Branch do
875
- attributes :length
876
- end
877
-
878
- map Fissure, to: Fissure
879
- end
880
- engine.mapper_for(Tree)
881
- end
882
-
883
- def configure_has_one
884
- engine = Vorpal.define do
885
- map Trunk do
886
- attributes :length
887
- has_one :tree
888
- end
889
-
890
- map Tree do
891
- attributes :name
892
- end
893
- end
894
- engine.mapper_for(Trunk)
895
- end
896
-
897
- def configure_unowned_has_one
898
- engine = Vorpal.define do
899
- map Trunk do
900
- attributes :length
901
- has_one :tree, owned: false
902
- end
903
-
904
- map Tree do
905
- attributes :name
906
- end
907
- end
908
- engine.mapper_for(Trunk)
909
- end
910
- end