perpetuity 1.0.0 → 1.0.1
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 +7 -7
- data/CHANGELOG.md +4 -0
- data/lib/perpetuity/data_injectable.rb +1 -1
- data/lib/perpetuity/mapper.rb +2 -2
- data/lib/perpetuity/rails_model.rb +12 -0
- data/lib/perpetuity/version.rb +1 -1
- data/perpetuity.gemspec +1 -1
- data/spec/integration/associations_spec.rb +12 -10
- data/spec/integration/deletion_spec.rb +1 -1
- data/spec/integration/enumerable_spec.rb +9 -9
- data/spec/integration/indexing_spec.rb +11 -8
- data/spec/integration/pagination_spec.rb +4 -4
- data/spec/integration/persistence_spec.rb +17 -16
- data/spec/integration/retrieval_spec.rb +48 -48
- data/spec/integration/serialization_spec.rb +5 -5
- data/spec/integration/update_spec.rb +9 -9
- data/spec/perpetuity/attribute_set_spec.rb +2 -2
- data/spec/perpetuity/attribute_spec.rb +7 -7
- data/spec/perpetuity/config_spec.rb +15 -14
- data/spec/perpetuity/data_injectable_spec.rb +5 -5
- data/spec/perpetuity/dereferencer_spec.rb +9 -8
- data/spec/perpetuity/dirty_tracker_spec.rb +6 -6
- data/spec/perpetuity/duplicator_spec.rb +8 -8
- data/spec/perpetuity/identity_map_spec.rb +4 -4
- data/spec/perpetuity/mapper_registry_spec.rb +4 -4
- data/spec/perpetuity/mapper_spec.rb +45 -39
- data/spec/perpetuity/rails_model_spec.rb +27 -16
- data/spec/perpetuity/reference_spec.rb +7 -2
- data/spec/perpetuity/retrieval_spec.rb +21 -21
- data/spec/perpetuity_spec.rb +10 -10
- metadata +49 -45
@@ -45,16 +45,16 @@ describe 'serialization' do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'serializes objects into hashes' do
|
48
|
-
mapper.serialize(article).
|
48
|
+
expect(mapper.serialize(article)).to be == serialized_value
|
49
49
|
end
|
50
50
|
|
51
51
|
it 'deserializes hashes into proper objects' do
|
52
52
|
unserialized = mapper.find mapper.id_for(article)
|
53
|
-
unserialized.
|
54
|
-
unserialized.title.
|
55
|
-
unserialized.body.
|
53
|
+
expect(unserialized).to be_a Article
|
54
|
+
expect(unserialized.title).to be == article.title
|
55
|
+
expect(unserialized.body).to be == article.body
|
56
56
|
unserialized.comments.first.tap do |unserialized_comment|
|
57
|
-
unserialized_comment.body.
|
57
|
+
expect(unserialized_comment.body).to be == comment.body
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
@@ -12,13 +12,13 @@ describe 'updating' do
|
|
12
12
|
|
13
13
|
it 'updates an object in the database' do
|
14
14
|
mapper.update article, title: new_title
|
15
|
-
mapper.find(mapper.id_for article).title.
|
15
|
+
expect(mapper.find(mapper.id_for article).title).to eq new_title
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'resaves the object in the database' do
|
19
19
|
article.title = new_title
|
20
20
|
mapper.save article
|
21
|
-
mapper.find(mapper.id_for article).title.
|
21
|
+
expect(mapper.find(mapper.id_for article).title).to eq new_title
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'only updates attributes which have changed since last retrieval' do
|
@@ -35,8 +35,8 @@ describe 'updating' do
|
|
35
35
|
second_mapper.save second_article
|
36
36
|
|
37
37
|
canonical_article = mapper.find(article_id)
|
38
|
-
canonical_article.title.
|
39
|
-
canonical_article.views.
|
38
|
+
expect(canonical_article.title).to be == 'New title'
|
39
|
+
expect(canonical_article.views).to be == 7
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'updates an object with referenced attributes' do
|
@@ -49,7 +49,7 @@ describe 'updating' do
|
|
49
49
|
mapper.save retrieved_article
|
50
50
|
|
51
51
|
retrieved_article = mapper.find(mapper.id_for retrieved_article)
|
52
|
-
retrieved_article.author.
|
52
|
+
expect(retrieved_article.author).to be_a Perpetuity::Reference
|
53
53
|
end
|
54
54
|
|
55
55
|
it 'updates an object with an array of referenced attributes' do
|
@@ -66,8 +66,8 @@ describe 'updating' do
|
|
66
66
|
mapper.save retrieved_book
|
67
67
|
|
68
68
|
retrieved_authors = Perpetuity[Book].find(mapper.id_for retrieved_book).authors
|
69
|
-
retrieved_authors.map(&:klass).
|
70
|
-
retrieved_authors.map(&:id).
|
69
|
+
expect(retrieved_authors.map(&:klass)).to be == [User, User]
|
70
|
+
expect(retrieved_authors.map(&:id)).to be == [mapper.id_for(dave), mapper.id_for(andy)]
|
71
71
|
end
|
72
72
|
|
73
73
|
describe 'atomic increments/decrements' do
|
@@ -77,13 +77,13 @@ describe 'updating' do
|
|
77
77
|
it 'increments attributes of objects in the database' do
|
78
78
|
mapper.increment article, :views
|
79
79
|
mapper.increment article, :views, 10
|
80
|
-
mapper.find(mapper.id_for(article)).views.
|
80
|
+
expect(mapper.find(mapper.id_for(article)).views).to be == view_count + 11
|
81
81
|
end
|
82
82
|
|
83
83
|
it 'decrements attributes of objects in the database' do
|
84
84
|
mapper.decrement article, :views
|
85
85
|
mapper.decrement article, :views, 10
|
86
|
-
mapper.find(mapper.id_for(article)).views.
|
86
|
+
expect(mapper.find(mapper.id_for(article)).views).to be == view_count - 11
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
@@ -6,14 +6,14 @@ module Perpetuity
|
|
6
6
|
attribute = double('Attribute', name: :foo)
|
7
7
|
subject << attribute
|
8
8
|
|
9
|
-
subject.first.
|
9
|
+
expect(subject.first).to eq attribute
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'can access attributes by name' do
|
13
13
|
user_attribute = double('Attribute', name: :user)
|
14
14
|
subject << user_attribute
|
15
15
|
|
16
|
-
subject[:user].
|
16
|
+
expect(subject[:user]).to eq user_attribute
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -6,29 +6,29 @@ module Perpetuity
|
|
6
6
|
subject { attribute }
|
7
7
|
|
8
8
|
it 'has a name' do
|
9
|
-
subject.name.
|
9
|
+
expect(subject.name).to be == :article
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'has a type' do
|
13
|
-
subject.type.
|
13
|
+
expect(subject.type).to be == Object
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'can get extra options' do
|
17
|
-
attribute.options.
|
18
|
-
attribute.options(:default).
|
17
|
+
expect(attribute.options).to be == { default: 1 }
|
18
|
+
expect(attribute.options(:default)).to be == 1
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'can be embedded' do
|
22
22
|
attribute = Attribute.new :article, Object, embedded: true
|
23
|
-
attribute.
|
23
|
+
expect(attribute).to be_embedded
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'can match a regex' do
|
27
|
-
expect(attribute =~ /article/).to
|
27
|
+
expect(attribute =~ /article/).to be_truthy
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'uses its name when converted to a string' do
|
31
|
-
attribute.to_s.
|
31
|
+
expect(attribute.to_s).to be == 'article'
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -3,6 +3,7 @@ require 'perpetuity/postgres'
|
|
3
3
|
|
4
4
|
module Perpetuity
|
5
5
|
describe Configuration do
|
6
|
+
before(:all) { Perpetuity.register_standard_adapters }
|
6
7
|
let(:config) { Configuration.new }
|
7
8
|
|
8
9
|
it 'sets a data source' do
|
@@ -13,28 +14,28 @@ module Perpetuity
|
|
13
14
|
host: 'host',
|
14
15
|
port: 1337
|
15
16
|
|
16
|
-
config.data_source.
|
17
|
-
config.data_source.db.
|
18
|
-
config.data_source.username.
|
19
|
-
config.data_source.password.
|
20
|
-
config.data_source.host.
|
21
|
-
config.data_source.port.
|
17
|
+
expect(config.data_source).to be_a Postgres
|
18
|
+
expect(config.data_source.db).to eq 'perpetuity'
|
19
|
+
expect(config.data_source.username).to eq 'username'
|
20
|
+
expect(config.data_source.password).to eq 'password'
|
21
|
+
expect(config.data_source.host).to eq 'host'
|
22
|
+
expect(config.data_source.port).to eq 1337
|
22
23
|
end
|
23
24
|
|
24
25
|
it 'allows a URL as its data source' do
|
25
26
|
db = "postgres://username:password@host:1337/database"
|
26
27
|
data_source = config.data_source(db, pool_size: 20)
|
27
|
-
data_source.
|
28
|
-
data_source.username.
|
29
|
-
data_source.password.
|
30
|
-
data_source.host.
|
31
|
-
data_source.port.
|
32
|
-
data_source.db.
|
33
|
-
data_source.pool_size.
|
28
|
+
expect(data_source).to be_a Postgres
|
29
|
+
expect(data_source.username).to eq 'username'
|
30
|
+
expect(data_source.password).to eq 'password'
|
31
|
+
expect(data_source.host).to eq 'host'
|
32
|
+
expect(data_source.port).to eq 1337
|
33
|
+
expect(data_source.db).to eq 'database'
|
34
|
+
expect(data_source.pool_size).to eq 20
|
34
35
|
end
|
35
36
|
|
36
37
|
it 'sets up a logger by default' do
|
37
|
-
config.logger.
|
38
|
+
expect(config.logger).to be_a Logger
|
38
39
|
end
|
39
40
|
end
|
40
41
|
end
|
@@ -9,23 +9,23 @@ module Perpetuity
|
|
9
9
|
|
10
10
|
it 'injects an attribute into an object' do
|
11
11
|
klass.inject_attribute object, :a, 1
|
12
|
-
object.instance_variable_get(:@a).
|
12
|
+
expect(object.instance_variable_get(:@a)).to eq 1
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'injects data into an object' do
|
16
16
|
klass.inject_data object, { a: 1, b: 2 }
|
17
|
-
object.instance_variable_get(:@a).
|
18
|
-
object.instance_variable_get(:@b).
|
17
|
+
expect(object.instance_variable_get(:@a)).to eq 1
|
18
|
+
expect(object.instance_variable_get(:@b)).to eq 2
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'injects an id' do
|
22
22
|
klass.inject_data object, { id: 1 }
|
23
|
-
object.instance_variable_get(:@id).
|
23
|
+
expect(object.instance_variable_get(:@id)).to eq 1
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'injects a specified id' do
|
27
27
|
klass.give_id_to object, 2
|
28
|
-
object.instance_variable_get(:@id).
|
28
|
+
expect(object.instance_variable_get(:@id)).to eq 2
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -15,28 +15,29 @@ module Perpetuity
|
|
15
15
|
context 'with one reference' do
|
16
16
|
it 'loads objects based on the specified objects and attribute' do
|
17
17
|
first.instance_variable_set :@id, 1
|
18
|
-
mapper.
|
18
|
+
expect(mapper).to receive(:find).with(1) { first }
|
19
19
|
id_map = IdentityMap.new
|
20
|
-
derefer.
|
21
|
-
registry.
|
22
|
-
|
20
|
+
allow(derefer).to receive(:map) { id_map }
|
21
|
+
allow(registry).to receive(:mapper_for)
|
22
|
+
.with(Object, identity_map: id_map)
|
23
|
+
.and_return mapper
|
23
24
|
|
24
25
|
derefer.load first_ref
|
25
26
|
id = derefer[first_ref].instance_variable_get(:@id)
|
26
|
-
id.
|
27
|
+
expect(id).to be == 1
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
30
31
|
context 'with no references' do
|
31
32
|
it 'returns an empty array' do
|
32
|
-
derefer.load(nil).
|
33
|
+
expect(derefer.load(nil)).to be == []
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
37
|
context 'with multiple references' do
|
37
38
|
it 'returns the array of dereferenced objects' do
|
38
|
-
mapper.
|
39
|
-
derefer.load([first_ref, second_ref]).
|
39
|
+
expect(mapper).to receive(:find).with([1, 2]) { objects }
|
40
|
+
expect(derefer.load([first_ref, second_ref])).to be == objects
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
@@ -18,7 +18,7 @@ module Perpetuity
|
|
18
18
|
let(:object) { klass.new(1, 'foo') }
|
19
19
|
|
20
20
|
before do
|
21
|
-
mapper.
|
21
|
+
allow(mapper).to receive(:id_for).with(object) { object.id }
|
22
22
|
tracker << object
|
23
23
|
end
|
24
24
|
|
@@ -26,23 +26,23 @@ module Perpetuity
|
|
26
26
|
object.name = 'bar'
|
27
27
|
retrieved = tracker[klass, 1]
|
28
28
|
|
29
|
-
retrieved.id.
|
30
|
-
retrieved.name.
|
29
|
+
expect(retrieved.id).to be == 1
|
30
|
+
expect(retrieved.name).to be == 'foo'
|
31
31
|
end
|
32
32
|
|
33
33
|
specify 'the object returned is a duplicate' do
|
34
|
-
tracker[klass, 1].
|
34
|
+
expect(tracker[klass, 1]).not_to be object
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'stringifies keys when checking' do
|
38
38
|
retrieved = tracker[klass, '1']
|
39
|
-
retrieved.id.
|
39
|
+
expect(retrieved.id).to be == 1
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
43
|
context 'when the object does not exist in the IdentityMap' do
|
44
44
|
it 'returns nil' do
|
45
|
-
tracker[Object, 1].
|
45
|
+
expect(tracker[Object, 1]).to be_nil
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -9,27 +9,27 @@ module Perpetuity
|
|
9
9
|
let(:duper) { Duplicator.new(book) }
|
10
10
|
|
11
11
|
it 'duplicates an object' do
|
12
|
-
duper.object.
|
13
|
-
duper.object.
|
12
|
+
expect(duper.object).to be_a Book
|
13
|
+
expect(duper.object).not_to be book
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'duplicates attributes inside an object' do
|
17
17
|
duped_book = duper.object
|
18
|
-
duped_book.title.
|
19
|
-
duped_book.title.
|
20
|
-
duped_book.title.
|
18
|
+
expect(duped_book.title).to be_a String
|
19
|
+
expect(duped_book.title).to be == book.title
|
20
|
+
expect(duped_book.title).not_to be book.title
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'does not duplicate non-duplicable attributes' do
|
24
24
|
# Symbols cannot be duped
|
25
25
|
book = Book.new(:foo)
|
26
26
|
duper = Duplicator.new(book)
|
27
|
-
duper.object.title.
|
27
|
+
expect(duper.object.title).to be :foo
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'duplicates objects contained within array attributes' do
|
31
|
-
duper.object.authors.first.
|
32
|
-
duper.object.authors.first.
|
31
|
+
expect(duper.object.authors.first).to be_a User
|
32
|
+
expect(duper.object.authors.first).not_to be authors.first
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -21,23 +21,23 @@ module Perpetuity
|
|
21
21
|
it 'returns the object with the given class and id' do
|
22
22
|
retrieved = id_map[klass, 1]
|
23
23
|
|
24
|
-
retrieved.id.
|
24
|
+
expect(retrieved.id).to be == 1
|
25
25
|
end
|
26
26
|
|
27
27
|
specify 'the object returned is the same object' do
|
28
|
-
id_map[klass, 1].
|
28
|
+
expect(id_map[klass, 1]).to be object
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'when the object does not exist in the IdentityMap' do
|
33
33
|
it 'returns nil' do
|
34
|
-
id_map[Object, 1].
|
34
|
+
expect(id_map[Object, 1]).to be_nil
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'returns all of the ids it contains' do
|
39
39
|
id_map << object
|
40
|
-
id_map.ids_for(klass).
|
40
|
+
expect(id_map.ids_for(klass)).to be == [1]
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -11,7 +11,7 @@ module Perpetuity
|
|
11
11
|
|
12
12
|
it { should have_mapper Object }
|
13
13
|
it 'maps classes to instances of their mappers' do
|
14
|
-
registry[Object].
|
14
|
+
expect(registry[Object]).to be_a mapper
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'raises a KeyError when trying to find a mapper for a missing class' do
|
@@ -26,8 +26,8 @@ module Perpetuity
|
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'loads the definition for the specified mapper class' do
|
29
|
-
Dir.
|
30
|
-
registry.
|
29
|
+
expect(Dir).to receive(:[]).with('app/**/*_mapper.rb') { [mapper_file] }
|
30
|
+
expect(registry).to receive(:load).with(mapper_file)
|
31
31
|
registry.load_mappers
|
32
32
|
end
|
33
33
|
end
|
@@ -35,7 +35,7 @@ module Perpetuity
|
|
35
35
|
it 'returns a mapper initialized with the specified identity map' do
|
36
36
|
identity_map = double('IdentityMap')
|
37
37
|
mapper = registry.mapper_for(Object, identity_map: identity_map)
|
38
|
-
mapper.identity_map.
|
38
|
+
expect(mapper.identity_map).to be identity_map
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -13,49 +13,49 @@ module Perpetuity
|
|
13
13
|
|
14
14
|
it 'has correct attributes' do
|
15
15
|
mapper_class.attribute :name
|
16
|
-
mapper_class.attributes.
|
16
|
+
expect(mapper_class.attributes).to eq [:name]
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'returns an empty attribute list when no attributes have been assigned' do
|
20
|
-
mapper_class.attributes.
|
20
|
+
expect(mapper_class.attributes).to be_empty
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'can have embedded attributes' do
|
24
24
|
mapper_class.attribute :comments, embedded: true
|
25
|
-
mapper_class.attribute_set[:comments].
|
25
|
+
expect(mapper_class.attribute_set[:comments]).to be_embedded
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'registers itself with the mapper registry' do
|
29
29
|
mapper_class.map Object, registry
|
30
|
-
registry[Object].
|
30
|
+
expect(registry[Object]).to be_instance_of mapper_class
|
31
31
|
end
|
32
32
|
|
33
33
|
describe 'talking to the data source' do
|
34
34
|
let(:data_source) { MongoDB.new(db: nil) }
|
35
35
|
before do
|
36
|
-
mapper_class.
|
36
|
+
allow(mapper_class).to receive(:data_source) { data_source }
|
37
37
|
mapper_class.map Object, registry
|
38
38
|
end
|
39
39
|
|
40
40
|
specify 'mappers use the data source that the mapper class uses' do
|
41
|
-
mapper.data_source.
|
41
|
+
expect(mapper.data_source).to be data_source
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'inserts objects into a data source' do
|
45
45
|
mapper_class.attribute :my_attribute
|
46
46
|
obj = Object.new
|
47
47
|
obj.instance_variable_set '@my_attribute', 'foo'
|
48
|
-
data_source.
|
49
|
-
data_source.
|
48
|
+
expect(data_source).to receive(:can_serialize?).with('foo') { true }
|
49
|
+
expect(data_source).to receive(:insert)
|
50
50
|
.with('Object', [{ 'my_attribute' => 'foo' }], mapper.attribute_set)
|
51
51
|
.and_return(['bar'])
|
52
52
|
|
53
|
-
mapper.insert(obj).
|
53
|
+
expect(mapper.insert(obj)).to be == 'bar'
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'counts objects of its mapped class in the data source' do
|
57
|
-
data_source.
|
58
|
-
mapper.count.
|
57
|
+
expect(data_source).to receive(:count).with('Object') { 4 }
|
58
|
+
expect(mapper.count).to be == 4
|
59
59
|
end
|
60
60
|
|
61
61
|
describe 'finding specific objects' do
|
@@ -65,10 +65,10 @@ module Perpetuity
|
|
65
65
|
it 'finds an object by ID' do
|
66
66
|
returned_object.instance_variable_set :@id, 1
|
67
67
|
criteria = data_source.query { |o| o.id == 1 }
|
68
|
-
data_source.
|
68
|
+
expect(data_source).to receive(:retrieve)
|
69
69
|
.with('Object', criteria, options) { [returned_object] }
|
70
70
|
|
71
|
-
mapper.find(1).
|
71
|
+
expect(mapper.find(1)).to be == returned_object
|
72
72
|
end
|
73
73
|
|
74
74
|
it 'finds multiple objects by ID' do
|
@@ -77,38 +77,38 @@ module Perpetuity
|
|
77
77
|
mapper.give_id_to second, 2
|
78
78
|
criteria = data_source.query { |o| o.id.in [1, 2] }
|
79
79
|
options.merge! limit: nil
|
80
|
-
data_source.
|
80
|
+
expect(data_source).to receive(:retrieve)
|
81
81
|
.with('Object', criteria, options)
|
82
82
|
.and_return [first, second]
|
83
83
|
|
84
|
-
mapper.find([1, 2]).to_a.
|
84
|
+
expect(mapper.find([1, 2]).to_a).to be == [first, second]
|
85
85
|
end
|
86
86
|
|
87
87
|
it 'finds multiple objects with a block' do
|
88
88
|
criteria = data_source.query { |o| o.name == 'foo' }
|
89
89
|
options = self.options.merge(limit: nil)
|
90
|
-
data_source.
|
90
|
+
expect(data_source).to receive(:retrieve)
|
91
91
|
.with('Object', criteria, options) { [returned_object] }.twice
|
92
92
|
|
93
|
-
mapper.select { |e| e.name == 'foo' }.to_a.
|
94
|
-
mapper.find_all { |e| e.name == 'foo' }.to_a.
|
93
|
+
expect(mapper.select { |e| e.name == 'foo' }.to_a).to be == [returned_object]
|
94
|
+
expect(mapper.find_all { |e| e.name == 'foo' }.to_a).to be == [returned_object]
|
95
95
|
end
|
96
96
|
|
97
97
|
it 'finds an object with a block' do
|
98
98
|
criteria = data_source.query { |o| o.name == 'foo' }
|
99
|
-
data_source.
|
99
|
+
expect(data_source).to receive(:retrieve)
|
100
100
|
.with('Object', criteria, options) { [returned_object] }.twice
|
101
|
-
mapper.find { |o| o.name == 'foo' }.
|
102
|
-
mapper.detect { |o| o.name == 'foo' }.
|
101
|
+
expect(mapper.find { |o| o.name == 'foo' }).to be == returned_object
|
102
|
+
expect(mapper.detect { |o| o.name == 'foo' }).to be == returned_object
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'caches results' do
|
106
106
|
mapper.give_id_to returned_object, 1
|
107
107
|
criteria = data_source.query { |o| o.id == 1 }
|
108
108
|
duplicate = returned_object.dup
|
109
|
-
duplicate.
|
110
|
-
returned_object.
|
111
|
-
data_source.
|
109
|
+
allow(duplicate).to receive(:class) { returned_object.class }
|
110
|
+
allow(returned_object).to receive(:dup) { duplicate }
|
111
|
+
expect(data_source).to receive(:retrieve)
|
112
112
|
.with('Object', criteria, options) { [returned_object] }
|
113
113
|
.once
|
114
114
|
|
@@ -118,7 +118,7 @@ module Perpetuity
|
|
118
118
|
|
119
119
|
it 'does not cache nil results' do
|
120
120
|
criteria = data_source.query { |o| o.id == 1 }
|
121
|
-
data_source.
|
121
|
+
expect(data_source).to receive(:retrieve)
|
122
122
|
.with('Object', criteria, options) { [] }
|
123
123
|
.twice
|
124
124
|
|
@@ -132,8 +132,8 @@ module Perpetuity
|
|
132
132
|
object = Object.new
|
133
133
|
mapper.give_id_to object, 1
|
134
134
|
object.instance_variable_set '@foo', 'bar'
|
135
|
-
data_source.
|
136
|
-
data_source.
|
135
|
+
expect(data_source).to receive(:can_serialize?).with('bar') { true }
|
136
|
+
expect(data_source).to receive(:update).with 'Object', 1, { 'foo' => 'bar' }
|
137
137
|
|
138
138
|
mapper.save object
|
139
139
|
end
|
@@ -149,7 +149,7 @@ module Perpetuity
|
|
149
149
|
|
150
150
|
object.instance_variable_set :@modified, true
|
151
151
|
|
152
|
-
mapper.serialize_changed_attributes(object).
|
152
|
+
expect(mapper.serialize_changed_attributes(object)).to be == {
|
153
153
|
'modified' => true
|
154
154
|
}
|
155
155
|
end
|
@@ -157,12 +157,12 @@ module Perpetuity
|
|
157
157
|
it 'deletes an object from the data source' do
|
158
158
|
object = Object.new
|
159
159
|
|
160
|
-
data_source.
|
160
|
+
expect(data_source).to receive(:delete).with [object], 'Object'
|
161
161
|
mapper.delete object
|
162
162
|
end
|
163
163
|
|
164
164
|
it 'deletes all objects it manages' do
|
165
|
-
data_source.
|
165
|
+
expect(data_source).to receive(:delete_all).with('Object')
|
166
166
|
mapper.delete_all
|
167
167
|
end
|
168
168
|
end
|
@@ -174,21 +174,27 @@ module Perpetuity
|
|
174
174
|
before { mapper.give_id_to object, 1 }
|
175
175
|
|
176
176
|
it 'knows the object is persisted' do
|
177
|
-
mapper.persisted?(object).
|
177
|
+
expect(mapper.persisted?(object)).to be_truthy
|
178
178
|
end
|
179
179
|
|
180
180
|
it 'knows the id of the object' do
|
181
|
-
mapper.id_for(object).
|
181
|
+
expect(mapper.id_for(object)).to be == 1
|
182
182
|
end
|
183
183
|
end
|
184
184
|
|
185
185
|
context 'when not persisted' do
|
186
186
|
it 'knows the object is not persisted' do
|
187
|
-
mapper.persisted?(object).
|
187
|
+
expect(mapper.persisted?(object)).to be_falsey
|
188
188
|
end
|
189
189
|
|
190
190
|
it 'returns a nil id' do
|
191
|
-
mapper.id_for(object).
|
191
|
+
expect(mapper.id_for(object)).to be_nil
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'knows an object is not persisted even when id is nil' do
|
195
|
+
mapper.give_id_to object, nil
|
196
|
+
|
197
|
+
expect(mapper.persisted?(object)).to be_falsey
|
192
198
|
end
|
193
199
|
end
|
194
200
|
end
|
@@ -198,14 +204,14 @@ module Perpetuity
|
|
198
204
|
it 'adds the attribute to the attribute set' do
|
199
205
|
mapper_class.id(String) { 1.to_s }
|
200
206
|
id_attr = mapper_class.attribute_set[:id]
|
201
|
-
id_attr.type.
|
207
|
+
expect(id_attr.type).to be String
|
202
208
|
end
|
203
209
|
end
|
204
210
|
|
205
211
|
context 'when not setting the type' do
|
206
212
|
it 'does not add the attribute' do
|
207
213
|
mapper_class.id { 1.to_s }
|
208
|
-
mapper_class.attribute_set[:id].
|
214
|
+
expect(mapper_class.attribute_set[:id]).to be_nil
|
209
215
|
end
|
210
216
|
end
|
211
217
|
end
|
@@ -215,19 +221,19 @@ module Perpetuity
|
|
215
221
|
registry = Object.new
|
216
222
|
id_map = Object.new
|
217
223
|
mapper = Mapper.new(registry, id_map)
|
218
|
-
mapper.identity_map.
|
224
|
+
expect(mapper.identity_map).to be id_map
|
219
225
|
end
|
220
226
|
end
|
221
227
|
|
222
228
|
describe 'specifying the collection/table name' do
|
223
229
|
it 'changes the collection name' do
|
224
230
|
mapper_class.collection_name = 'articles'
|
225
|
-
mapper.collection_name.
|
231
|
+
expect(mapper.collection_name).to be == 'articles'
|
226
232
|
end
|
227
233
|
|
228
234
|
it 'defaults to the mapped class name' do
|
229
235
|
mapper_class.map Object
|
230
|
-
mapper.collection_name.
|
236
|
+
expect(mapper.collection_name).to be == 'Object'
|
231
237
|
end
|
232
238
|
end
|
233
239
|
end
|