perpetuity 0.3.1 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +12 -0
- data/README.md +12 -6
- data/lib/perpetuity/mongodb/query.rb +1 -1
- data/lib/perpetuity/version.rb +1 -1
- data/spec/perpetuity/mongodb/query_spec.rb +7 -7
- data/spec/perpetuity_spec.rb +8 -8
- data/spec/test_classes.rb +4 -2
- metadata +2 -2
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## Version 0.4
|
2
|
+
|
3
|
+
- Mapper select DSL now more closely resembles `Enumerable` syntax
|
4
|
+
- Instead of `mapper.select { published_at < Time.now }` you would write `mapper.select { |article| article.published_at < Time.now }`
|
5
|
+
- It's a little more typing, but it eliminates a lot of problems that came from calling instance_exec on the block. It meant we couldn't call methods on the current object (they would be invoked on the `Query` object) or use instance variables from the current object.
|
6
|
+
- Explained more in [issue #19](https://github.com/jgaskins/perpetuity/issues/19)
|
7
|
+
|
8
|
+
## Version 0.3.1
|
9
|
+
|
10
|
+
- Access object state via instance methods to store actual object state, rather than treating all objects as value objects
|
11
|
+
- Use `Object.allocate` rather than `Object.new` when restoring state to an object from the database
|
12
|
+
|
1
13
|
## Version 0.3
|
2
14
|
|
3
15
|
- Use `Perpetuity[]` instead of `Perpetuity::Mapper[]` to get mapper instances
|
data/README.md
CHANGED
@@ -72,18 +72,16 @@ You can load specific objects by calling the `find` method with an ID param on t
|
|
72
72
|
|
73
73
|
```ruby
|
74
74
|
article = Perpetuity[Article].find params[:id]
|
75
|
-
users = Perpetuity[User].select { email == 'me@example.com' }
|
76
|
-
articles = Perpetuity[Article].select { published_at < Time.now }
|
77
|
-
comments = Perpetuity[Comment].select { article_id.in articles.map(&:id) }
|
75
|
+
users = Perpetuity[User].select { |user| user.email == 'me@example.com' }
|
76
|
+
articles = Perpetuity[Article].select { |article| article.published_at < Time.now }
|
77
|
+
comments = Perpetuity[Comment].select { |comment| comment.article_id.in articles.map(&:id) }
|
78
78
|
```
|
79
79
|
|
80
|
-
Unfortunately, due to limitations in the Ruby language itself, this is as close as I could get to a true `Enumerable`-style select method. Once I can override `&&` and `||`, we can put more Rubyesque code in here.
|
81
|
-
|
82
80
|
These methods will return a Perpetuity::Retrieval object, which will lazily retrieve the objects from the database. They will wait to hit the DB when you begin iterating over the objects so you can continue chaining methods.
|
83
81
|
|
84
82
|
```ruby
|
85
83
|
article_mapper = Perpetuity[Article]
|
86
|
-
articles = article_mapper.select { published_at < Time.now }
|
84
|
+
articles = article_mapper.select { |article| article.published_at < Time.now }
|
87
85
|
articles = articles.sort(:published_at).reverse
|
88
86
|
articles = articles.page(2).per_page(10) # built-in pagination
|
89
87
|
|
@@ -92,6 +90,14 @@ articles.each do |article| # This is when the DB gets hit
|
|
92
90
|
end
|
93
91
|
```
|
94
92
|
|
93
|
+
Unfortunately, due to limitations in the Ruby language itself, we cannot get a true `Enumerable`-style select method. The limitation shows itself when needing to have multiple criteria for a query, as in this super-secure example:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
user = Perpetuity[User].select { |user| (user.email == params[:email]) & (user.password == params[:password]) }
|
97
|
+
```
|
98
|
+
|
99
|
+
Notice that we have to use a single `&` and surround each criterion with parentheses. If we could override `&&` and `||`, we could put more Rubyesque code in here, but until then, we have to operate within the boundaries of the operators that can be overridden.
|
100
|
+
|
95
101
|
## Associations with Other Objects
|
96
102
|
|
97
103
|
The database can natively serialize some objects. For example, MongoDB can serialize `String`, `Numeric`, `Array`, `Hash`, `Time`, `nil`, `true`, `false`, and a few others. If an object references another type of object (such as an article referencing its author, a `User` object), the association is declared just as any other attribute. No special treatment is required.
|
data/lib/perpetuity/version.rb
CHANGED
@@ -5,33 +5,33 @@ module Perpetuity
|
|
5
5
|
let(:query) { MongoDB::Query }
|
6
6
|
|
7
7
|
it 'generates Mongo equality expressions' do
|
8
|
-
query.new{name == 'Jamie'}.to_db.should == {name: 'Jamie'}
|
8
|
+
query.new{ |user| user.name == 'Jamie' }.to_db.should == {name: 'Jamie'}
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'generates Mongo less-than expressions' do
|
12
|
-
query.new{quantity < 10}.to_db.should == {quantity: { '$lt' => 10}}
|
12
|
+
query.new{ |v| v.quantity < 10 }.to_db.should == {quantity: { '$lt' => 10}}
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'generates Mongo less-than-or-equal expressions' do
|
16
|
-
query.new{quantity <= 10}.to_db.should == {quantity: { '$lte' => 10}}
|
16
|
+
query.new{ |v| v.quantity <= 10 }.to_db.should == {quantity: { '$lte' => 10}}
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'generates Mongo greater-than expressions' do
|
20
|
-
query.new{quantity > 10}.to_db.should == {quantity: { '$gt' => 10}}
|
20
|
+
query.new{ |v| v.quantity > 10 }.to_db.should == {quantity: { '$gt' => 10}}
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'generates Mongo greater-than-or-equal expressions' do
|
24
|
-
query.new{quantity >= 10}.to_db.should == {quantity: { '$gte' => 10}}
|
24
|
+
query.new{ |v| v.quantity >= 10 }.to_db.should == {quantity: { '$gte' => 10}}
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'generates Mongo inequality expressions' do
|
28
|
-
query.new{name.not_equal? 'Jamie'}.to_db.should == {
|
28
|
+
query.new{ |user| user.name.not_equal? 'Jamie' }.to_db.should == {
|
29
29
|
name: {'$ne' => 'Jamie'}
|
30
30
|
}
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'generates Mongo regexp expressions' do
|
34
|
-
query.new{name =~ /Jamie/}.to_db.should == {name: /Jamie/}
|
34
|
+
query.new{ |user| user.name =~ /Jamie/ }.to_db.should == {name: /Jamie/}
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
data/spec/perpetuity_spec.rb
CHANGED
@@ -163,55 +163,55 @@ describe Perpetuity do
|
|
163
163
|
end
|
164
164
|
|
165
165
|
it 'selects objects using equality' do
|
166
|
-
selected = Perpetuity[Article].select { title == 'Published' }
|
166
|
+
selected = Perpetuity[Article].select { |article| article.title == 'Published' }
|
167
167
|
selected.map(&:id).should include published.id
|
168
168
|
selected.map(&:id).should_not include draft.id
|
169
169
|
end
|
170
170
|
|
171
171
|
it 'selects objects using greater-than' do
|
172
|
-
selected = Perpetuity[Article].select { published_at < Time.now }
|
172
|
+
selected = Perpetuity[Article].select { |article| article.published_at < Time.now }
|
173
173
|
ids = selected.map(&:id)
|
174
174
|
ids.should include published.id
|
175
175
|
ids.should_not include draft.id
|
176
176
|
end
|
177
177
|
|
178
178
|
it 'selects objects using greater-than-or-equal' do
|
179
|
-
selected = Perpetuity[Article].select { views >= 3 }
|
179
|
+
selected = Perpetuity[Article].select { |article| article.views >= 3 }
|
180
180
|
ids = selected.map(&:id)
|
181
181
|
ids.should include published.id
|
182
182
|
ids.should_not include draft.id
|
183
183
|
end
|
184
184
|
|
185
185
|
it 'selects objects using less-than' do
|
186
|
-
selected = Perpetuity[Article].select { views < 3 }
|
186
|
+
selected = Perpetuity[Article].select { |article| article.views < 3 }
|
187
187
|
ids = selected.map(&:id)
|
188
188
|
ids.should include draft.id
|
189
189
|
ids.should_not include published.id
|
190
190
|
end
|
191
191
|
|
192
192
|
it 'selects objects using less-than-or-equal' do
|
193
|
-
selected = Perpetuity[Article].select { views <= 0 }
|
193
|
+
selected = Perpetuity[Article].select { |article| article.views <= 0 }
|
194
194
|
ids = selected.map(&:id)
|
195
195
|
ids.should include draft.id
|
196
196
|
ids.should_not include published.id
|
197
197
|
end
|
198
198
|
|
199
199
|
it 'selects objects using inequality' do
|
200
|
-
selected = Perpetuity[Article].select { title.not_equal? 'Draft' }
|
200
|
+
selected = Perpetuity[Article].select { |article| article.title.not_equal? 'Draft' }
|
201
201
|
ids = selected.map(&:id)
|
202
202
|
ids.should_not include draft.id
|
203
203
|
ids.should include published.id
|
204
204
|
end
|
205
205
|
|
206
206
|
it 'selects objects using regular expressions' do
|
207
|
-
selected = Perpetuity[Article].select { title =~ /Pub/ }
|
207
|
+
selected = Perpetuity[Article].select { |article| article.title =~ /Pub/ }
|
208
208
|
ids = selected.map(&:id)
|
209
209
|
ids.should include published.id
|
210
210
|
ids.should_not include draft.id
|
211
211
|
end
|
212
212
|
|
213
213
|
it 'selects objects using inclusion' do
|
214
|
-
selected = Perpetuity[Article].select { title.in %w( Published ) }
|
214
|
+
selected = Perpetuity[Article].select { |article| article.title.in %w( Published ) }
|
215
215
|
ids = selected.map(&:id)
|
216
216
|
ids.should include published.id
|
217
217
|
ids.should_not include draft.id
|
data/spec/test_classes.rb
CHANGED
@@ -31,11 +31,13 @@ class ArticleMapper < Perpetuity::Mapper
|
|
31
31
|
attribute :views
|
32
32
|
|
33
33
|
def published
|
34
|
-
select { (published_at.not_equal? nil) &
|
34
|
+
select { |article| (article.published_at.not_equal? nil) &
|
35
|
+
(article.published_at < Time.now) }
|
35
36
|
end
|
36
37
|
|
37
38
|
def unpublished
|
38
|
-
select { (published_at == nil) |
|
39
|
+
select { |article| (article.published_at == nil) |
|
40
|
+
(article.published_at > Time.now) }
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perpetuity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.4'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|