vorpal 1.0.2 → 1.3.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.
- checksums.yaml +4 -4
- data/README.md +73 -26
- data/lib/vorpal/aggregate_mapper.rb +13 -2
- data/lib/vorpal/aggregate_traversal.rb +9 -8
- data/lib/vorpal/config/association_config.rb +84 -0
- data/lib/vorpal/config/belongs_to_config.rb +35 -0
- data/lib/vorpal/config/class_config.rb +71 -0
- data/lib/vorpal/config/configs.rb +54 -0
- data/lib/vorpal/config/foreign_key_info.rb +23 -0
- data/lib/vorpal/config/has_many_config.rb +38 -0
- data/lib/vorpal/config/has_one_config.rb +35 -0
- data/lib/vorpal/config/main_config.rb +68 -0
- data/lib/vorpal/db_loader.rb +25 -22
- data/lib/vorpal/driver/postgresql.rb +42 -6
- data/lib/vorpal/dsl/config_builder.rb +26 -73
- data/lib/vorpal/dsl/configuration.rb +139 -42
- data/lib/vorpal/dsl/defaults_generator.rb +1 -1
- data/lib/vorpal/engine.rb +27 -13
- data/lib/vorpal/exceptions.rb +4 -0
- data/lib/vorpal/identity_map.rb +7 -2
- data/lib/vorpal/loaded_objects.rb +57 -14
- data/lib/vorpal/util/array_hash.rb +22 -8
- data/lib/vorpal/util/hash_initialization.rb +1 -1
- data/lib/vorpal/version.rb +1 -1
- data/vorpal.gemspec +4 -5
- metadata +18 -78
- data/.editorconfig +0 -13
- data/.envrc +0 -4
- data/.gitignore +0 -16
- data/.rspec +0 -1
- data/.ruby-version +0 -1
- data/.travis.yml +0 -18
- data/.yardopts +0 -1
- data/Appraisals +0 -18
- data/Gemfile +0 -4
- data/Rakefile +0 -39
- data/bin/appraisal +0 -29
- data/bin/rake +0 -29
- data/bin/rspec +0 -29
- data/docker-compose.yml +0 -19
- data/gemfiles/rails_5_1.gemfile +0 -11
- data/gemfiles/rails_5_1.gemfile.lock +0 -101
- data/gemfiles/rails_5_2.gemfile +0 -11
- data/gemfiles/rails_5_2.gemfile.lock +0 -101
- data/gemfiles/rails_6_0.gemfile +0 -9
- data/gemfiles/rails_6_0.gemfile.lock +0 -101
- data/lib/vorpal/configs.rb +0 -296
- data/spec/acceptance/vorpal/aggregate_mapper_spec.rb +0 -910
- data/spec/helpers/codecov_helper.rb +0 -7
- data/spec/helpers/db_helpers.rb +0 -69
- data/spec/helpers/profile_helpers.rb +0 -26
- data/spec/integration/vorpal/driver/postgresql_spec.rb +0 -42
- data/spec/integration_spec_helper.rb +0 -29
- data/spec/performance/vorpal/performance_spec.rb +0 -305
- data/spec/unit/vorpal/configs_spec.rb +0 -117
- data/spec/unit/vorpal/db_loader_spec.rb +0 -103
- data/spec/unit/vorpal/dsl/config_builder_spec.rb +0 -18
- data/spec/unit/vorpal/dsl/defaults_generator_spec.rb +0 -75
- data/spec/unit/vorpal/identity_map_spec.rb +0 -62
- data/spec/unit/vorpal/loaded_objects_spec.rb +0 -22
- data/spec/unit/vorpal/util/string_utils_spec.rb +0 -25
- data/spec/unit_spec_helper.rb +0 -1
@@ -1,117 +0,0 @@
|
|
1
|
-
require 'unit_spec_helper'
|
2
|
-
require 'vorpal/configs'
|
3
|
-
|
4
|
-
describe Vorpal::MasterConfig do
|
5
|
-
class Post
|
6
|
-
attr_accessor :comments
|
7
|
-
attr_accessor :best_comment
|
8
|
-
end
|
9
|
-
|
10
|
-
class Comment
|
11
|
-
attr_accessor :post
|
12
|
-
end
|
13
|
-
|
14
|
-
let(:post_config) { Vorpal::ClassConfig.new(domain_class: Post) }
|
15
|
-
let(:comment_config) { Vorpal::ClassConfig.new(domain_class: Comment) }
|
16
|
-
let(:post_has_many_comments_config) { Vorpal::HasManyConfig.new(name: 'comments', fk: 'post_id', child_class: Comment) }
|
17
|
-
let(:post_has_one_comment_config) { Vorpal::HasOneConfig.new(name: 'best_comment', fk: 'post_id', child_class: Comment) }
|
18
|
-
let(:comment_belongs_to_post_config) { Vorpal::BelongsToConfig.new(name: 'post', fk: 'post_id', child_classes: [Post]) }
|
19
|
-
|
20
|
-
describe 'local_association_configs' do
|
21
|
-
it 'builds an association_config for a belongs_to' do
|
22
|
-
comment_config.belongs_tos << comment_belongs_to_post_config
|
23
|
-
|
24
|
-
Vorpal::MasterConfig.new([post_config, comment_config])
|
25
|
-
|
26
|
-
expect(comment_config.local_association_configs.size).to eq(1)
|
27
|
-
expect(post_config.local_association_configs.size).to eq(0)
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'sets the association end configs' do
|
31
|
-
comment_config.belongs_tos << comment_belongs_to_post_config
|
32
|
-
post_config.has_manys << post_has_many_comments_config
|
33
|
-
|
34
|
-
Vorpal::MasterConfig.new([post_config, comment_config])
|
35
|
-
|
36
|
-
association_config = comment_config.local_association_configs.first
|
37
|
-
|
38
|
-
expect(association_config.remote_end_config).to eq(post_has_many_comments_config)
|
39
|
-
expect(association_config.local_end_config).to eq(comment_belongs_to_post_config)
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'builds an association_config for a has_many' do
|
43
|
-
post_config.has_manys << post_has_many_comments_config
|
44
|
-
|
45
|
-
Vorpal::MasterConfig.new([post_config, comment_config])
|
46
|
-
|
47
|
-
expect(comment_config.local_association_configs.size).to eq(1)
|
48
|
-
expect(post_config.local_association_configs.size).to eq(0)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe 'nice user feedback' do
|
53
|
-
it 'lets the user know what the problem is when a configuration is missing' do
|
54
|
-
master_config = Vorpal::MasterConfig.new([])
|
55
|
-
|
56
|
-
expect {
|
57
|
-
master_config.config_for(String)
|
58
|
-
}.to raise_error(Vorpal::ConfigurationNotFound, "No configuration found for String")
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe Vorpal::AssociationConfig do
|
63
|
-
describe 'associate' do
|
64
|
-
let(:post) { Post.new }
|
65
|
-
let(:comment) { Comment.new }
|
66
|
-
|
67
|
-
it 'sets both ends of a one-to-one association' do
|
68
|
-
config = Vorpal::AssociationConfig.new(comment_config, 'post_id', nil)
|
69
|
-
config.add_remote_class_config(post_config)
|
70
|
-
|
71
|
-
config.local_end_config = comment_belongs_to_post_config
|
72
|
-
config.remote_end_config = post_has_one_comment_config
|
73
|
-
|
74
|
-
config.associate(comment, post)
|
75
|
-
|
76
|
-
expect(comment.post).to eq(post)
|
77
|
-
expect(post.best_comment).to eq(comment)
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'sets both ends of a one-to-many association' do
|
81
|
-
config = Vorpal::AssociationConfig.new(comment_config, 'post_id', nil)
|
82
|
-
config.add_remote_class_config(post_config)
|
83
|
-
|
84
|
-
config.local_end_config = comment_belongs_to_post_config
|
85
|
-
config.remote_end_config = post_has_many_comments_config
|
86
|
-
|
87
|
-
config.associate(comment, post)
|
88
|
-
|
89
|
-
expect(comment.post).to eq(post)
|
90
|
-
expect(post.comments).to eq([comment])
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
describe 'remote_class_config' do
|
95
|
-
it 'works with non-polymorphic associations' do
|
96
|
-
config = Vorpal::AssociationConfig.new(comment_config, 'post_id', nil)
|
97
|
-
config.add_remote_class_config(post_config)
|
98
|
-
|
99
|
-
post = Post.new
|
100
|
-
class_config = config.remote_class_config(post)
|
101
|
-
|
102
|
-
expect(class_config).to eq(post_config)
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'works with polymorphic associations' do
|
106
|
-
config = Vorpal::AssociationConfig.new(comment_config, 'commented_upon_id', 'commented_upon_type')
|
107
|
-
config.add_remote_class_config(post_config)
|
108
|
-
config.add_remote_class_config(comment_config)
|
109
|
-
|
110
|
-
comment = double('comment', commented_upon_type: 'Comment')
|
111
|
-
class_config = config.remote_class_config(comment)
|
112
|
-
|
113
|
-
expect(class_config).to eq(comment_config)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
@@ -1,103 +0,0 @@
|
|
1
|
-
require 'unit_spec_helper'
|
2
|
-
require 'vorpal'
|
3
|
-
require 'virtus'
|
4
|
-
|
5
|
-
describe Vorpal::DbLoader do
|
6
|
-
|
7
|
-
class Post; end
|
8
|
-
|
9
|
-
class Comment
|
10
|
-
include Virtus.model
|
11
|
-
|
12
|
-
attribute :id, Integer
|
13
|
-
attribute :post, Post
|
14
|
-
end
|
15
|
-
|
16
|
-
class Post
|
17
|
-
include Virtus.model
|
18
|
-
|
19
|
-
attribute :id, Integer
|
20
|
-
attribute :best_comment, Comment
|
21
|
-
attribute :comments, Array[Comment]
|
22
|
-
end
|
23
|
-
|
24
|
-
class PostDB
|
25
|
-
include Virtus.model
|
26
|
-
attribute :id, Integer
|
27
|
-
attribute :best_comment_id, Integer
|
28
|
-
end
|
29
|
-
|
30
|
-
class CommentDB
|
31
|
-
include Virtus.model
|
32
|
-
attribute :id, Integer
|
33
|
-
attribute :post_id, Integer
|
34
|
-
end
|
35
|
-
|
36
|
-
before(:all) do
|
37
|
-
# define_table('comments', {post_id: :integer}, false)
|
38
|
-
# CommentDB = defineAr('comments')
|
39
|
-
|
40
|
-
# define_table('posts', {best_comment_id: :integer}, false)
|
41
|
-
# PostDB = defineAr('posts')
|
42
|
-
end
|
43
|
-
|
44
|
-
# it 'loads an object once even when referred to by different associations of different types2' do
|
45
|
-
# post_config = Vorpal.build_class_config(Post) do
|
46
|
-
# attributes :name
|
47
|
-
# belongs_to :best_comment, child_class: Comment
|
48
|
-
# has_many :comments
|
49
|
-
# end
|
50
|
-
#
|
51
|
-
# comment_config = Vorpal.build_class_config(Comment) do
|
52
|
-
# attributes :length
|
53
|
-
# end
|
54
|
-
#
|
55
|
-
# master_config = Vorpal::MasterConfig.new([post_config, comment_config])
|
56
|
-
#
|
57
|
-
# driver = Vorpal::Postgresql.new
|
58
|
-
#
|
59
|
-
# best_comment_db = CommentDB.create!
|
60
|
-
# post_db = PostDB.create!(best_comment_id: best_comment_db.id)
|
61
|
-
# best_comment_db.update_attributes!(post_id: post_db.id)
|
62
|
-
#
|
63
|
-
# loader = Vorpal::DbLoader.new(false, driver)
|
64
|
-
# loaded_objects = loader.load_from_db([post_db.id], master_config.config_for(Post))
|
65
|
-
# p loaded_objects.all_objects
|
66
|
-
# # expect(loaded_objects.all_objects.size).to eq(2)
|
67
|
-
#
|
68
|
-
# repo = Vorpal::AggregateMapper.new(driver, master_config)
|
69
|
-
# post = repo.load(post_db.id, Post)
|
70
|
-
# p post
|
71
|
-
# expect(post.comments.size).to eq(1)
|
72
|
-
# end
|
73
|
-
|
74
|
-
it 'loads an object once even when referred to by different associations of different types with stubs' do
|
75
|
-
post_config = Vorpal.build_class_config(Post, to: PostDB) do
|
76
|
-
attributes :name
|
77
|
-
belongs_to :best_comment, child_class: Comment
|
78
|
-
has_many :comments
|
79
|
-
end
|
80
|
-
|
81
|
-
comment_config = Vorpal.build_class_config(Comment, to: CommentDB) do
|
82
|
-
attributes :length
|
83
|
-
end
|
84
|
-
|
85
|
-
Vorpal::MasterConfig.new([post_config, comment_config])
|
86
|
-
|
87
|
-
best_comment_db = CommentDB.new
|
88
|
-
best_comment_db.id = 99
|
89
|
-
post_db = PostDB.new(best_comment_id: best_comment_db.id)
|
90
|
-
post_db.id = 100
|
91
|
-
best_comment_db.post_id = post_db.id
|
92
|
-
|
93
|
-
driver = instance_double("Vorpal::Driver::Postgresql")
|
94
|
-
expect(driver).to receive(:load_by_id).with(PostDB, [post_db.id]).and_return([post_db])
|
95
|
-
expect(driver).to receive(:load_by_id).with(CommentDB, [best_comment_db.id]).and_return([best_comment_db])
|
96
|
-
expect(driver).to receive(:load_by_foreign_key).and_return([best_comment_db])
|
97
|
-
|
98
|
-
loader = Vorpal::DbLoader.new(false, driver)
|
99
|
-
loaded_objects = loader.load_from_db([post_db.id], post_config)
|
100
|
-
|
101
|
-
expect(loaded_objects.all_objects).to contain_exactly(post_db, best_comment_db)
|
102
|
-
end
|
103
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'unit_spec_helper'
|
2
|
-
|
3
|
-
require 'vorpal/dsl/config_builder'
|
4
|
-
|
5
|
-
describe Vorpal::Dsl::ConfigBuilder do
|
6
|
-
class Tester; end
|
7
|
-
|
8
|
-
let(:builder) { Vorpal::Dsl::ConfigBuilder.new(Tester, {}, nil) }
|
9
|
-
|
10
|
-
describe 'mapping attributes' do
|
11
|
-
it 'allows the \'attributes\' method to be called multiple times' do
|
12
|
-
builder.attributes :first
|
13
|
-
builder.attributes :second
|
14
|
-
|
15
|
-
expect(builder.attributes_with_id).to eq([:id, :first, :second])
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
require 'unit_spec_helper'
|
2
|
-
|
3
|
-
require 'vorpal/dsl/defaults_generator'
|
4
|
-
require 'vorpal/driver/postgresql'
|
5
|
-
|
6
|
-
describe Vorpal::Dsl::DefaultsGenerator do
|
7
|
-
class Tester; end
|
8
|
-
class Author; end
|
9
|
-
module Namespace
|
10
|
-
class Tester; end
|
11
|
-
class Author; end
|
12
|
-
end
|
13
|
-
|
14
|
-
let(:db_driver) { instance_double(Vorpal::Driver::Postgresql)}
|
15
|
-
|
16
|
-
describe '#build_db_class' do
|
17
|
-
it 'derives the table_name from the domain class name' do
|
18
|
-
generator = build_generator(Tester)
|
19
|
-
expect(db_driver).to receive(:build_db_class).with(Tester, "testers")
|
20
|
-
|
21
|
-
generator.build_db_class(nil)
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'specifies the table_name manually' do
|
25
|
-
generator = build_generator(Tester)
|
26
|
-
expect(db_driver).to receive(:build_db_class).with(Tester, "override")
|
27
|
-
|
28
|
-
generator.build_db_class("override")
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe '#table_name' do
|
33
|
-
it 'namespaces the table name' do
|
34
|
-
generator = build_generator(Namespace::Tester)
|
35
|
-
|
36
|
-
expect(generator.table_name).to eq("namespace/testers")
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe '#child_class' do
|
41
|
-
it 'resolves the associated class' do
|
42
|
-
generator = build_generator(Tester)
|
43
|
-
clazz = generator.child_class("author")
|
44
|
-
|
45
|
-
expect(clazz.name).to eq("Author")
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'resolves the associated class in the same namespace as the owning class' do
|
49
|
-
generator = build_generator(Namespace::Tester)
|
50
|
-
clazz = generator.child_class("author")
|
51
|
-
|
52
|
-
expect(clazz.name).to eq("Namespace::Author")
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
describe '#foreign_key' do
|
57
|
-
it 'generates a foreign key from an association name' do
|
58
|
-
generator = build_generator(Tester)
|
59
|
-
fk_name = generator.foreign_key("author")
|
60
|
-
|
61
|
-
expect(fk_name).to eq("author_id")
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'generates a foreign key from an association name regardless of the namespace of the owning class' do
|
65
|
-
generator = build_generator(Namespace::Tester)
|
66
|
-
fk_name = generator.foreign_key("author")
|
67
|
-
|
68
|
-
expect(fk_name).to eq("author_id")
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def build_generator(domain_clazz)
|
73
|
-
Vorpal::Dsl::DefaultsGenerator.new(domain_clazz, db_driver)
|
74
|
-
end
|
75
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
require 'unit_spec_helper'
|
2
|
-
|
3
|
-
require 'vorpal/identity_map'
|
4
|
-
|
5
|
-
describe Vorpal::IdentityMap do
|
6
|
-
let(:map) { Vorpal::IdentityMap.new }
|
7
|
-
|
8
|
-
it "does not rely on the key object's implementation of hash and eql?" do
|
9
|
-
funny1 = build_funny_entity(1)
|
10
|
-
map.set(funny1, 'funny 1')
|
11
|
-
|
12
|
-
funny2 = build_funny_entity(2)
|
13
|
-
map.set(funny2, 'funny 2')
|
14
|
-
|
15
|
-
expect(map.get(funny1)).to eq('funny 1')
|
16
|
-
end
|
17
|
-
|
18
|
-
it "raises an exception when the key object does not have an id set" do
|
19
|
-
entity = build_entity(nil)
|
20
|
-
|
21
|
-
expect { map.set(entity, 'something') }.to raise_error(/Cannot map a DB row/)
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'raises an exception when the key object extends a class with no name (such as anonymous classes)' do
|
25
|
-
anonymous_class = Class.new do
|
26
|
-
attr_accessor :id
|
27
|
-
end
|
28
|
-
|
29
|
-
entity = anonymous_class.new
|
30
|
-
entity.id = 1
|
31
|
-
|
32
|
-
expect { map.set(entity, 'something') }.to raise_error(/Cannot map a DB row/)
|
33
|
-
end
|
34
|
-
|
35
|
-
def build_entity(id)
|
36
|
-
entity = Entity.new
|
37
|
-
entity.id = id
|
38
|
-
entity
|
39
|
-
end
|
40
|
-
|
41
|
-
class Entity
|
42
|
-
attr_accessor :id
|
43
|
-
end
|
44
|
-
|
45
|
-
def build_funny_entity(id)
|
46
|
-
funny1 = Funny.new
|
47
|
-
funny1.id = id
|
48
|
-
funny1
|
49
|
-
end
|
50
|
-
|
51
|
-
class Funny
|
52
|
-
attr_accessor :id
|
53
|
-
|
54
|
-
def hash
|
55
|
-
1
|
56
|
-
end
|
57
|
-
|
58
|
-
def eql?(other)
|
59
|
-
true
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'unit_spec_helper'
|
2
|
-
|
3
|
-
require 'virtus'
|
4
|
-
require 'vorpal/loaded_objects'
|
5
|
-
require 'vorpal/configs'
|
6
|
-
|
7
|
-
describe Vorpal::LoadedObjects do
|
8
|
-
class TestObject
|
9
|
-
include Virtus.model
|
10
|
-
attribute :id, Integer
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'does not accept duplicate objects' do
|
14
|
-
object = TestObject.new(id: 22)
|
15
|
-
config = Vorpal::ClassConfig.new({domain_class: Object})
|
16
|
-
|
17
|
-
subject.add(config, [object, object])
|
18
|
-
subject.add(config, [object])
|
19
|
-
|
20
|
-
expect(subject.objects.values.flatten).to contain_exactly(object)
|
21
|
-
end
|
22
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'unit_spec_helper'
|
2
|
-
require 'vorpal/util/string_utils'
|
3
|
-
|
4
|
-
describe Vorpal::Util::StringUtils do
|
5
|
-
|
6
|
-
describe '.escape_class_name' do
|
7
|
-
it 'does nothing when there are no :: in the class name' do
|
8
|
-
expect(escape_class_name("Foo")).to eq("Foo")
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'converts :: into __' do
|
12
|
-
expect(escape_class_name("Foo::Bar")).to eq("Foo__Bar")
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'converts multiple :: into __' do
|
16
|
-
expect(escape_class_name("Foo::Bar::Baz")).to eq("Foo__Bar__Baz")
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def escape_class_name(class_name)
|
23
|
-
Vorpal::Util::StringUtils.escape_class_name(class_name)
|
24
|
-
end
|
25
|
-
end
|
data/spec/unit_spec_helper.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'helpers/codecov_helper'
|