perpetuity 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -0
- data/lib/perpetuity/data_injectable.rb +0 -3
- data/lib/perpetuity/identity_map.rb +4 -2
- data/lib/perpetuity/mapper.rb +25 -8
- data/lib/perpetuity/mongodb/serializer.rb +9 -3
- data/lib/perpetuity/reference.rb +6 -2
- data/lib/perpetuity/version.rb +1 -1
- data/lib/perpetuity.rb +0 -1
- data/spec/integration/associations_spec.rb +8 -7
- data/spec/integration/indexing_spec.rb +5 -0
- data/spec/integration/mongodb_spec.rb +7 -1
- data/spec/integration/persistence_spec.rb +28 -24
- data/spec/integration/retrieval_spec.rb +34 -33
- data/spec/integration/serialization_spec.rb +3 -3
- data/spec/integration/update_spec.rb +9 -9
- data/spec/perpetuity/data_injectable_spec.rb +2 -2
- data/spec/perpetuity/dereferencer_spec.rb +6 -12
- data/spec/perpetuity/identity_map_spec.rb +12 -3
- data/spec/perpetuity/mapper_spec.rb +49 -2
- data/spec/perpetuity/mongodb/serializer_spec.rb +47 -12
- data/spec/perpetuity/reference_spec.rb +4 -0
- data/spec/perpetuity_spec.rb +19 -12
- data/spec/support/test_classes/car.rb +6 -0
- metadata +281 -143
- checksums.yaml +0 -7
- data/lib/perpetuity/persisted_object.rb +0 -7
- data/spec/perpetuity/persisted_object_spec.rb +0 -16
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## Version 0.6.0
|
2
|
+
|
3
|
+
- Stop extending persisted/retrieved objects with `Perpetuity::PersistedObject`. Extending these objects invalidates method caches inside the VM, which degrades performance.
|
4
|
+
- Cache all objects returned from `Mapper#find(id)` by default into the mapper object. This can be bypassed with `Mapper#find(id, false)`
|
5
|
+
- Do not store uninitialized attributes with the MongoDB serializer. This shrinks the size of documents when possible.
|
6
|
+
|
1
7
|
## Version 0.5.0
|
2
8
|
|
3
9
|
- Allow querying based on referenced class/id or embedded-object data
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'perpetuity/persisted_object'
|
2
|
-
|
3
1
|
module Perpetuity
|
4
2
|
module DataInjectable
|
5
3
|
def inject_attribute object, attribute, value
|
@@ -17,7 +15,6 @@ module Perpetuity
|
|
17
15
|
if args.any?
|
18
16
|
inject_attribute object, :id, args.first
|
19
17
|
end
|
20
|
-
object.extend PersistedObject
|
21
18
|
end
|
22
19
|
end
|
23
20
|
end
|
@@ -7,11 +7,13 @@ module Perpetuity
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def [] klass, id
|
10
|
-
map[klass][id]
|
10
|
+
map[klass][id.to_s]
|
11
11
|
end
|
12
12
|
|
13
13
|
def << object
|
14
|
-
|
14
|
+
klass = object.class
|
15
|
+
id = object.instance_variable_get(:@id)
|
16
|
+
map[klass][id.to_s] = object
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
data/lib/perpetuity/mapper.rb
CHANGED
@@ -8,10 +8,11 @@ require 'perpetuity/retrieval'
|
|
8
8
|
module Perpetuity
|
9
9
|
class Mapper
|
10
10
|
include DataInjectable
|
11
|
-
attr_reader :mapper_registry
|
11
|
+
attr_reader :mapper_registry, :identity_map
|
12
12
|
|
13
13
|
def initialize registry=Perpetuity.mapper_registry
|
14
14
|
@mapper_registry = registry
|
15
|
+
@identity_map = IdentityMap.new
|
15
16
|
end
|
16
17
|
|
17
18
|
def self.map klass, registry=Perpetuity.mapper_registry
|
@@ -106,12 +107,20 @@ module Perpetuity
|
|
106
107
|
|
107
108
|
alias :find_all :select
|
108
109
|
|
109
|
-
def find
|
110
|
+
def find id=nil, cache_result=true, &block
|
110
111
|
if block_given?
|
111
112
|
select(&block).first
|
112
113
|
else
|
113
|
-
|
114
|
-
|
114
|
+
cached_value = identity_map[mapped_class, id]
|
115
|
+
return cached_value if cached_value
|
116
|
+
|
117
|
+
result = select { |object| object.id == id }.first
|
118
|
+
|
119
|
+
if cache_result and !result.nil?
|
120
|
+
identity_map << result
|
121
|
+
end
|
122
|
+
|
123
|
+
result
|
115
124
|
end
|
116
125
|
end
|
117
126
|
|
@@ -122,7 +131,7 @@ module Perpetuity
|
|
122
131
|
end
|
123
132
|
|
124
133
|
def delete object
|
125
|
-
id =
|
134
|
+
id = persisted?(object) ? id_for(object) : object
|
126
135
|
data_source.delete id, mapped_class
|
127
136
|
end
|
128
137
|
|
@@ -152,7 +161,7 @@ module Perpetuity
|
|
152
161
|
end
|
153
162
|
|
154
163
|
def update object, new_data, update_in_memory = true
|
155
|
-
id = object.is_a?(mapped_class) ? object
|
164
|
+
id = object.is_a?(mapped_class) ? id_for(object) : object
|
156
165
|
|
157
166
|
inject_data object, new_data if update_in_memory
|
158
167
|
data_source.update mapped_class, id, new_data
|
@@ -163,17 +172,25 @@ module Perpetuity
|
|
163
172
|
end
|
164
173
|
|
165
174
|
def increment object, attribute, count=1
|
166
|
-
data_source.increment mapped_class, object
|
175
|
+
data_source.increment mapped_class, id_for(object), attribute, count
|
167
176
|
rescue Moped::Errors::OperationFailure
|
168
177
|
raise ArgumentError.new('Attempted to increment a non-numeric value')
|
169
178
|
end
|
170
179
|
|
171
180
|
def decrement object, attribute, count=1
|
172
|
-
data_source.increment mapped_class, object
|
181
|
+
data_source.increment mapped_class, id_for(object), attribute, -count
|
173
182
|
rescue Moped::Errors::OperationFailure
|
174
183
|
raise ArgumentError.new('Attempted to decrement a non-numeric value')
|
175
184
|
end
|
176
185
|
|
186
|
+
def persisted? object
|
187
|
+
object.instance_variable_defined?(:@id)
|
188
|
+
end
|
189
|
+
|
190
|
+
def id_for object
|
191
|
+
object.instance_variable_get(:@id)
|
192
|
+
end
|
193
|
+
|
177
194
|
def self.validate &block
|
178
195
|
validations.instance_exec(&block)
|
179
196
|
end
|
@@ -17,8 +17,14 @@ module Perpetuity
|
|
17
17
|
object.instance_variable_get("@#{attribute_name}")
|
18
18
|
end
|
19
19
|
|
20
|
+
def has_attribute? object, attribute_name
|
21
|
+
object.instance_variable_defined? "@#{attribute_name}"
|
22
|
+
end
|
23
|
+
|
20
24
|
def serialize object
|
21
25
|
attrs = mapper.class.attribute_set.map do |attrib|
|
26
|
+
next unless has_attribute? object, attrib.name
|
27
|
+
|
22
28
|
value = attribute_for object, attrib.name
|
23
29
|
|
24
30
|
serialized_value = if value.is_a? Reference
|
@@ -36,7 +42,7 @@ module Perpetuity
|
|
36
42
|
[attrib.name.to_s, serialized_value]
|
37
43
|
end
|
38
44
|
|
39
|
-
Hash[attrs]
|
45
|
+
Hash[attrs.compact]
|
40
46
|
end
|
41
47
|
|
42
48
|
def unserialize data
|
@@ -134,10 +140,10 @@ module Perpetuity
|
|
134
140
|
if value.is_a? Reference
|
135
141
|
reference = value
|
136
142
|
else
|
137
|
-
unless
|
143
|
+
unless mapper.persisted? value
|
138
144
|
mapper_registry[value.class].insert value
|
139
145
|
end
|
140
|
-
reference = Reference.new(value.class.to_s, value
|
146
|
+
reference = Reference.new(value.class.to_s, mapper.id_for(value))
|
141
147
|
end
|
142
148
|
{
|
143
149
|
'__metadata__' => {
|
data/lib/perpetuity/reference.rb
CHANGED
@@ -7,11 +7,15 @@ module Perpetuity
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def == other
|
10
|
-
|
10
|
+
if other.is_a? self.class
|
11
|
+
klass == other.klass && id == other.id
|
12
|
+
else
|
13
|
+
other.is_a?(klass) && id == other.id
|
14
|
+
end
|
11
15
|
end
|
12
16
|
|
13
17
|
def eql? other
|
14
|
-
self == other
|
18
|
+
other.is_a?(self.class) && self == other
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
data/lib/perpetuity/version.rb
CHANGED
data/lib/perpetuity.rb
CHANGED
@@ -17,16 +17,16 @@ describe 'associations with other objects' do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
describe 'referenced relationships' do
|
20
|
-
let(:creator) { topic_mapper.find(topic
|
20
|
+
let(:creator) { topic_mapper.find(topic_mapper.id_for topic).creator }
|
21
21
|
subject { creator }
|
22
22
|
|
23
23
|
it { should be_a Perpetuity::Reference }
|
24
24
|
its(:klass) { should be User }
|
25
|
-
its(:id) { should be == user
|
25
|
+
its(:id) { should be == user_mapper.id_for(user) }
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'can retrieve a one-to-one association' do
|
29
|
-
retrieved_topic = topic_mapper.find(topic
|
29
|
+
retrieved_topic = topic_mapper.find(topic_mapper.id_for topic)
|
30
30
|
|
31
31
|
topic_mapper.load_association! retrieved_topic, :creator
|
32
32
|
retrieved_topic.creator.name.should eq 'Flump'
|
@@ -45,7 +45,7 @@ describe 'associations with other objects' do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'can retrieve a one-to-many association' do
|
48
|
-
persisted_book = book_mapper.find(pragprog_book
|
48
|
+
persisted_book = book_mapper.find(book_mapper.id_for pragprog_book)
|
49
49
|
book_mapper.load_association! persisted_book, :authors
|
50
50
|
|
51
51
|
persisted_book.authors.first.name.should be == 'Dave'
|
@@ -55,7 +55,7 @@ describe 'associations with other objects' do
|
|
55
55
|
it 'can retrieve a many-to-many association' do
|
56
56
|
cuke_authors.each { |author| Perpetuity[User].insert author }
|
57
57
|
book_mapper.insert cuke_book
|
58
|
-
book_ids = [pragprog_book, cuke_book].map(
|
58
|
+
book_ids = [pragprog_book, cuke_book].map { |book| book_mapper.id_for(book) }
|
59
59
|
|
60
60
|
books = book_mapper.select { |book| book.id.in book_ids }.to_a
|
61
61
|
book_mapper.load_association! books, :authors
|
@@ -70,7 +70,7 @@ describe 'associations with other objects' do
|
|
70
70
|
mapper = Perpetuity[Article]
|
71
71
|
|
72
72
|
mapper.insert article
|
73
|
-
retrieved = mapper.find(article
|
73
|
+
retrieved = mapper.find(mapper.id_for(article))
|
74
74
|
mapper.load_association! retrieved, :author
|
75
75
|
retrieved.author.should == [foo, bar]
|
76
76
|
end
|
@@ -90,7 +90,8 @@ describe 'associations with other objects' do
|
|
90
90
|
|
91
91
|
it 'serializes attributes' do
|
92
92
|
mapper.insert object
|
93
|
-
mapper.find(object
|
93
|
+
attr = mapper.find(mapper.id_for object).embedded_attribute
|
94
|
+
attr.should be == [unserializable_object]
|
94
95
|
end
|
95
96
|
end
|
96
97
|
end
|
@@ -14,7 +14,12 @@ describe 'indexing' do
|
|
14
14
|
index.attribute.to_s == :name
|
15
15
|
end
|
16
16
|
end
|
17
|
+
let(:db_name) { Perpetuity.configuration.data_source.db }
|
17
18
|
|
19
|
+
before do
|
20
|
+
Perpetuity.data_source :mongodb, db_name
|
21
|
+
mapper.data_source.drop_collection Object
|
22
|
+
end
|
18
23
|
after { mapper.data_source.drop_collection Object }
|
19
24
|
|
20
25
|
it 'adds indexes to database collections/tables' do
|
@@ -125,6 +125,7 @@ module Perpetuity
|
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'creates indexes on the database collection' do
|
128
|
+
mongo.delete_all collection
|
128
129
|
index = mongo.index collection, 'real_index', order: :descending, unique: true
|
129
130
|
mongo.activate_index! index
|
130
131
|
|
@@ -132,6 +133,7 @@ module Perpetuity
|
|
132
133
|
end
|
133
134
|
|
134
135
|
it 'removes indexes' do
|
136
|
+
mongo.drop_collection collection
|
135
137
|
index = mongo.index collection, 'real_index', order: :descending, unique: true
|
136
138
|
mongo.activate_index! index
|
137
139
|
mongo.remove_index index
|
@@ -156,7 +158,11 @@ module Perpetuity
|
|
156
158
|
let(:data) { { foo: 'bar' } }
|
157
159
|
let(:index) { mongo.index Object, :foo, unique: true }
|
158
160
|
|
159
|
-
before
|
161
|
+
before do
|
162
|
+
mongo.delete_all Object
|
163
|
+
mongo.activate_index! index
|
164
|
+
end
|
165
|
+
|
160
166
|
after { mongo.drop_collection Object }
|
161
167
|
|
162
168
|
it 'raises an exception when insertion fails' do
|
@@ -2,56 +2,61 @@ require 'spec_helper'
|
|
2
2
|
require 'support/test_classes'
|
3
3
|
|
4
4
|
describe 'Persistence' do
|
5
|
+
let(:mapper) { Perpetuity[Article] }
|
6
|
+
|
5
7
|
it "persists an object" do
|
6
8
|
article = Article.new 'I have a title'
|
7
|
-
expect {
|
8
|
-
to change {
|
9
|
-
|
9
|
+
expect { mapper.insert article }.
|
10
|
+
to change { mapper.count }.by 1
|
11
|
+
mapper.find(mapper.id_for(article)).title.should eq 'I have a title'
|
10
12
|
end
|
11
13
|
|
12
14
|
it 'returns the id of the persisted object' do
|
13
15
|
article = Article.new
|
14
|
-
|
16
|
+
mapper.insert(article).should eq mapper.id_for(article)
|
15
17
|
end
|
16
18
|
|
17
19
|
it "gives an id to objects" do
|
18
20
|
article = Article.new
|
19
|
-
|
21
|
+
mapper.give_id_to article, 1
|
20
22
|
|
21
|
-
article.
|
23
|
+
mapper.id_for(article).should eq 1
|
22
24
|
end
|
23
25
|
|
24
26
|
it 'persists referenced objects if they are not persisted' do
|
25
27
|
article = Article.new
|
26
28
|
article.author = User.new
|
27
|
-
|
29
|
+
mapper.insert article
|
28
30
|
|
29
|
-
|
31
|
+
retrieved = mapper.find(mapper.id_for(article))
|
32
|
+
mapper.id_for(retrieved.author).should be == mapper.id_for(article.author)
|
30
33
|
end
|
31
34
|
|
32
35
|
it 'persists arrays of referenced objects if they are not persisted' do
|
33
36
|
authors = [User.new('Dave'), User.new('Andy')]
|
34
37
|
book = Book.new
|
35
38
|
book.authors = authors
|
36
|
-
Perpetuity[Book]
|
39
|
+
mapper = Perpetuity[Book]
|
40
|
+
mapper.insert book
|
37
41
|
|
38
|
-
|
42
|
+
first_author = mapper.find(mapper.id_for book).authors.first
|
43
|
+
mapper.id_for(first_author).should be == mapper.id_for(authors.first)
|
39
44
|
end
|
40
45
|
|
41
46
|
describe 'id injection' do
|
42
47
|
let(:article) { Article.new }
|
43
48
|
|
44
49
|
it 'assigns an id to the inserted object' do
|
45
|
-
|
46
|
-
article.
|
50
|
+
mapper.insert article
|
51
|
+
mapper.id_for(article).should_not be_nil
|
47
52
|
end
|
48
53
|
|
49
54
|
it "assigns an id using Mapper.first" do
|
50
|
-
|
55
|
+
mapper.id_for(mapper.first).should_not be_nil
|
51
56
|
end
|
52
57
|
|
53
58
|
it 'assigns an id using Mapper.all.first' do
|
54
|
-
|
59
|
+
mapper.id_for(mapper.all.first).should_not be_nil
|
55
60
|
end
|
56
61
|
end
|
57
62
|
|
@@ -60,18 +65,17 @@ describe 'Persistence' do
|
|
60
65
|
|
61
66
|
it 'persists arrays' do
|
62
67
|
article.comments << 1 << 2 << 3
|
63
|
-
|
64
|
-
|
68
|
+
mapper.insert article
|
69
|
+
mapper.find(mapper.id_for article).comments.should eq [1, 2, 3]
|
65
70
|
end
|
66
71
|
|
67
72
|
it 'persists arrays with unserializable objects in them' do
|
68
73
|
comment = Comment.new('my comment')
|
69
74
|
article.comments << comment
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
end
|
75
|
+
mapper.insert article
|
76
|
+
persisted_comment = mapper.find(mapper.id_for article).comments.first
|
77
|
+
persisted_comment.should be_a Comment
|
78
|
+
persisted_comment.body.should eq comment.body
|
75
79
|
end
|
76
80
|
end
|
77
81
|
|
@@ -82,7 +86,7 @@ describe 'Persistence' do
|
|
82
86
|
|
83
87
|
it 'saves and retrieves hashes' do
|
84
88
|
user_mapper.insert user
|
85
|
-
user_mapper.find(user
|
89
|
+
user_mapper.find(user_mapper.id_for user).name.should be == name_hash
|
86
90
|
end
|
87
91
|
end
|
88
92
|
|
@@ -91,7 +95,7 @@ describe 'Persistence' do
|
|
91
95
|
book = Book.new("My Title #{noise}")
|
92
96
|
|
93
97
|
Perpetuity[Book].insert book
|
94
|
-
book.
|
98
|
+
Perpetuity[Book].id_for(book).should eq "my-title-#{noise}"
|
95
99
|
end
|
96
100
|
|
97
101
|
context 'with namespaced classes' do
|
@@ -102,7 +106,7 @@ describe 'Persistence' do
|
|
102
106
|
|
103
107
|
it 'persists even with colons in the names' do
|
104
108
|
mapper.insert person
|
105
|
-
person.should
|
109
|
+
mapper.persisted?(person).should be_true
|
106
110
|
end
|
107
111
|
end
|
108
112
|
end
|
@@ -4,23 +4,17 @@ require 'securerandom'
|
|
4
4
|
|
5
5
|
describe "retrieval" do
|
6
6
|
let(:mapper) { Perpetuity[Article] }
|
7
|
-
|
8
7
|
it "gets all the objects of a class" do
|
9
8
|
expect { mapper.insert Article.new }.
|
10
9
|
to change { mapper.all.to_a.count }.by 1
|
11
10
|
end
|
12
11
|
|
13
|
-
it "has an ID when retrieved" do
|
14
|
-
mapper.insert Article.new
|
15
|
-
mapper.first.should respond_to :id
|
16
|
-
end
|
17
|
-
|
18
12
|
it "gets an item with a specific ID" do
|
19
13
|
article = Article.new
|
20
14
|
mapper.insert article
|
21
|
-
retrieved = mapper.find(article
|
15
|
+
retrieved = mapper.find(mapper.id_for article)
|
22
16
|
|
23
|
-
retrieved.
|
17
|
+
mapper.id_for(retrieved).should be == mapper.id_for(article)
|
24
18
|
retrieved.title.should eq article.title
|
25
19
|
retrieved.body.should eq article.body
|
26
20
|
end
|
@@ -61,6 +55,10 @@ describe "retrieval" do
|
|
61
55
|
describe "Array-like syntax" do
|
62
56
|
let(:draft) { Article.new 'Draft', 'draft content', nil, Time.now + 30 }
|
63
57
|
let(:published) { Article.new 'Published', 'content', nil, Time.now - 30, 3 }
|
58
|
+
|
59
|
+
let(:published_id) { mapper.id_for published }
|
60
|
+
let(:draft_id) { mapper.id_for draft }
|
61
|
+
|
64
62
|
before do
|
65
63
|
mapper.insert draft
|
66
64
|
mapper.insert published
|
@@ -68,57 +66,58 @@ describe "retrieval" do
|
|
68
66
|
|
69
67
|
it 'selects objects using equality' do
|
70
68
|
selected = mapper.select { |article| article.title == 'Published' }
|
71
|
-
selected.map
|
72
|
-
|
69
|
+
ids = selected.map { |article| mapper.id_for article }
|
70
|
+
ids.should include published_id
|
71
|
+
ids.should_not include draft_id
|
73
72
|
end
|
74
73
|
|
75
74
|
it 'selects objects using greater-than' do
|
76
75
|
selected = mapper.select { |article| article.published_at < Time.now }
|
77
|
-
ids = selected.map
|
78
|
-
ids.should include
|
79
|
-
ids.should_not include
|
76
|
+
ids = selected.map { |article| mapper.id_for article }
|
77
|
+
ids.should include published_id
|
78
|
+
ids.should_not include draft_id
|
80
79
|
end
|
81
80
|
|
82
81
|
it 'selects objects using greater-than-or-equal' do
|
83
82
|
selected = mapper.select { |article| article.views >= 3 }
|
84
|
-
ids = selected.map
|
85
|
-
ids.should include
|
86
|
-
ids.should_not include
|
83
|
+
ids = selected.map { |article| mapper.id_for article }
|
84
|
+
ids.should include published_id
|
85
|
+
ids.should_not include draft_id
|
87
86
|
end
|
88
87
|
|
89
88
|
it 'selects objects using less-than' do
|
90
89
|
selected = mapper.select { |article| article.views < 3 }
|
91
|
-
ids = selected.map
|
92
|
-
ids.should include
|
93
|
-
ids.should_not include
|
90
|
+
ids = selected.map { |article| mapper.id_for article }
|
91
|
+
ids.should include draft_id
|
92
|
+
ids.should_not include published_id
|
94
93
|
end
|
95
94
|
|
96
95
|
it 'selects objects using less-than-or-equal' do
|
97
96
|
selected = mapper.select { |article| article.views <= 0 }
|
98
|
-
ids = selected.map
|
99
|
-
ids.should include
|
100
|
-
ids.should_not include
|
97
|
+
ids = selected.map { |article| mapper.id_for article }
|
98
|
+
ids.should include draft_id
|
99
|
+
ids.should_not include published_id
|
101
100
|
end
|
102
101
|
|
103
102
|
it 'selects objects using inequality' do
|
104
103
|
selected = mapper.select { |article| article.title != 'Draft' }
|
105
|
-
ids = selected.map
|
106
|
-
ids.should_not include
|
107
|
-
ids.should include
|
104
|
+
ids = selected.map { |article| mapper.id_for article }
|
105
|
+
ids.should_not include draft_id
|
106
|
+
ids.should include published_id
|
108
107
|
end
|
109
108
|
|
110
109
|
it 'selects objects using regular expressions' do
|
111
110
|
selected = mapper.select { |article| article.title =~ /Pub/ }
|
112
|
-
ids = selected.map
|
113
|
-
ids.should include
|
114
|
-
ids.should_not include
|
111
|
+
ids = selected.map { |article| mapper.id_for article }
|
112
|
+
ids.should include published_id
|
113
|
+
ids.should_not include draft_id
|
115
114
|
end
|
116
115
|
|
117
116
|
it 'selects objects using inclusion' do
|
118
117
|
selected = mapper.select { |article| article.title.in %w( Published ) }
|
119
|
-
ids = selected.map
|
120
|
-
ids.should include
|
121
|
-
ids.should_not include
|
118
|
+
ids = selected.map { |article| mapper.id_for article }
|
119
|
+
ids.should include published_id
|
120
|
+
ids.should_not include draft_id
|
122
121
|
end
|
123
122
|
end
|
124
123
|
|
@@ -171,7 +170,7 @@ describe "retrieval" do
|
|
171
170
|
|
172
171
|
it 'gets a CRM::Person object back' do
|
173
172
|
mapper.insert article
|
174
|
-
retrieved_article = mapper.find(article
|
173
|
+
retrieved_article = mapper.find(mapper.id_for article)
|
175
174
|
mapper.load_association! retrieved_article, :author
|
176
175
|
retrieved_article.author.should be_a CRM::Person
|
177
176
|
end
|
@@ -181,6 +180,8 @@ describe "retrieval" do
|
|
181
180
|
user = User.new(first_name: 'foo', last_name: 'bar')
|
182
181
|
mapper = Perpetuity[User]
|
183
182
|
mapper.insert user
|
184
|
-
mapper.select { |user| user.name.first_name == 'foo' }
|
183
|
+
users = mapper.select { |user| user.name.first_name == 'foo' }
|
184
|
+
ids = users.map { |retrieved_user| mapper.id_for(retrieved_user) }
|
185
|
+
ids.should include mapper.id_for(user)
|
185
186
|
end
|
186
187
|
end
|
@@ -13,7 +13,7 @@ describe 'serialization' do
|
|
13
13
|
'author' => {
|
14
14
|
'__metadata__' => {
|
15
15
|
'class' => author.class.to_s,
|
16
|
-
'id' => author
|
16
|
+
'id' => mapper.id_for(author)
|
17
17
|
}
|
18
18
|
},
|
19
19
|
'comments' => [
|
@@ -25,7 +25,7 @@ describe 'serialization' do
|
|
25
25
|
'author' => {
|
26
26
|
'__metadata__' => {
|
27
27
|
'class' => author.class.to_s,
|
28
|
-
'id' => author
|
28
|
+
'id' => mapper.id_for(author)
|
29
29
|
}
|
30
30
|
}
|
31
31
|
},
|
@@ -49,7 +49,7 @@ describe 'serialization' do
|
|
49
49
|
end
|
50
50
|
|
51
51
|
it 'deserializes hashes into proper objects' do
|
52
|
-
unserialized = mapper.find article
|
52
|
+
unserialized = mapper.find mapper.id_for(article)
|
53
53
|
unserialized.should be_a Article
|
54
54
|
unserialized.title.should be == article.title
|
55
55
|
unserialized.body.should be == article.body
|
@@ -12,7 +12,7 @@ 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(article
|
15
|
+
mapper.find(mapper.id_for article).title.should eq new_title
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'updates the object in memory' do
|
@@ -23,7 +23,7 @@ describe 'updating' do
|
|
23
23
|
it 'resaves the object in the database' do
|
24
24
|
article.title = new_title
|
25
25
|
mapper.save article
|
26
|
-
mapper.find(article
|
26
|
+
mapper.find(mapper.id_for article).title.should eq new_title
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'updates an object with referenced attributes' do
|
@@ -31,11 +31,11 @@ describe 'updating' do
|
|
31
31
|
article.author = user
|
32
32
|
mapper.save article
|
33
33
|
|
34
|
-
retrieved_article = mapper.find(article
|
34
|
+
retrieved_article = mapper.find(mapper.id_for article)
|
35
35
|
retrieved_article.title = new_title
|
36
36
|
mapper.save retrieved_article
|
37
37
|
|
38
|
-
retrieved_article = mapper.find(retrieved_article
|
38
|
+
retrieved_article = mapper.find(mapper.id_for retrieved_article)
|
39
39
|
retrieved_article.author.should be_a Perpetuity::Reference
|
40
40
|
end
|
41
41
|
|
@@ -48,13 +48,13 @@ describe 'updating' do
|
|
48
48
|
|
49
49
|
mapper.insert book
|
50
50
|
|
51
|
-
retrieved_book = mapper.find(book
|
51
|
+
retrieved_book = mapper.find(mapper.id_for book)
|
52
52
|
retrieved_book.authors << andy
|
53
53
|
mapper.save retrieved_book
|
54
54
|
|
55
|
-
retrieved_authors =
|
55
|
+
retrieved_authors = Perpetuity[Book].find(mapper.id_for retrieved_book).authors
|
56
56
|
retrieved_authors.map(&:klass).should == [User, User]
|
57
|
-
retrieved_authors.map(&:id).should == [dave
|
57
|
+
retrieved_authors.map(&:id).should == [mapper.id_for(dave), mapper.id_for(andy)]
|
58
58
|
end
|
59
59
|
|
60
60
|
describe 'atomic increments/decrements' do
|
@@ -64,13 +64,13 @@ describe 'updating' do
|
|
64
64
|
it 'increments attributes of objects in the database' do
|
65
65
|
mapper.increment article, :views
|
66
66
|
mapper.increment article, :views, 10
|
67
|
-
mapper.find(article
|
67
|
+
mapper.find(mapper.id_for(article)).views.should == view_count + 11
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'decrements attributes of objects in the database' do
|
71
71
|
mapper.decrement article, :views
|
72
72
|
mapper.decrement article, :views, 10
|
73
|
-
mapper.find(article
|
73
|
+
mapper.find(mapper.id_for(article)).views.should == view_count - 11
|
74
74
|
end
|
75
75
|
|
76
76
|
context 'with an object with the specified attribute missing' do
|
@@ -20,12 +20,12 @@ module Perpetuity
|
|
20
20
|
|
21
21
|
it 'injects an id' do
|
22
22
|
klass.inject_data object, { id: 1 }
|
23
|
-
object.id.should eq 1
|
23
|
+
object.instance_variable_get(:@id).should 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.id.should eq 2
|
28
|
+
object.instance_variable_get(:@id).should eq 2
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|