perpetuity 0.5.0 → 0.6.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.
- 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
|