opium 1.5.0 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/opium/model/criteria.rb +27 -26
- data/lib/opium/version.rb +1 -1
- data/spec/opium/model/criteria_spec.rb +72 -58
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: afcd218c0464f3b8a8b47c9f3203007f78a3096c
|
4
|
+
data.tar.gz: 899c86f06d5e7b5ff90e4fe24573964a0f4dc1f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aac084bb325da3d6b1bb5458c4c63cbf39e811daa97c3d06a48e96951937ac18d7b9af9b0b18d47b3cf5caa16574fba50d7412937516b99d704010ef43e689d9
|
7
|
+
data.tar.gz: 3deaf7216912daad377f38e4a4dd34afbf9d8be1c49cbe6b142a904d8558e7ba6905a350b7a12e3df9ae0bc8f546eca60a8e6f2bb60214bc76e736817e36a282
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## 1.5.1
|
2
|
+
### Resolved Issues
|
3
|
+
- Model::Criteria should now respond to #size correctly.
|
4
|
+
|
1
5
|
## 1.5.0
|
2
6
|
### New Features
|
3
7
|
- Opium will now work with ActiveModel 5.* going forward. Use a version before 1.5 if ActiveModel 4.* compatibility is needed. As a side-effect, supported rubies moves to anything above 2.2.2
|
data/lib/opium/model/criteria.rb
CHANGED
@@ -3,73 +3,73 @@ module Opium
|
|
3
3
|
class Criteria
|
4
4
|
include Opium::Model::Queryable::ClassMethods
|
5
5
|
include Enumerable
|
6
|
-
|
6
|
+
|
7
7
|
class_attribute :models
|
8
8
|
self.models = {}.with_indifferent_access
|
9
|
-
|
9
|
+
|
10
10
|
def initialize( model_name )
|
11
11
|
@model_name = model_name.respond_to?(:name) ? model_name.name : model_name
|
12
12
|
constraints[:count] = 1
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
attr_reader :model_name
|
16
|
-
|
16
|
+
|
17
17
|
def to_partial_path
|
18
18
|
model._to_partial_path
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def model
|
22
22
|
models[model_name] ||= model_name.constantize
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def chain
|
26
26
|
Marshal.load( Marshal.dump( self ) ).tap {|m| m.instance_variable_set( :@cache, nil )}
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def constraints
|
30
30
|
@constraints ||= {}.with_indifferent_access
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def update_constraint( constraint, value )
|
34
34
|
chain.tap {|c| c.update_constraint!( constraint, value )}
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def update_constraint!( constraint, value )
|
38
38
|
update_hash_value :constraints, constraint, value
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def constraints?
|
42
42
|
!constraints.except(:count).empty?
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def variables
|
46
46
|
@variables ||= {}.with_indifferent_access
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def update_variable( variable, value )
|
50
50
|
chain.tap {|c| c.update_variable!( variable, value )}
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def update_variable!( variable, value )
|
54
54
|
update_hash_value :variables, variable, value
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
def variables?
|
58
58
|
!variables.empty?
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
def empty?
|
62
62
|
count == 0
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
def criteria
|
66
66
|
self
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
def ==( other )
|
70
70
|
other.is_a?( self.class ) && self.model_name == other.model_name && self.constraints == other.constraints && self.variables == other.variables
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
def each(&block)
|
74
74
|
if !block_given?
|
75
75
|
to_enum(:each)
|
@@ -88,34 +88,35 @@ module Opium
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
def inspect
|
93
93
|
inspected_constraints = constraints.map {|k, v| [k, v.inspect].join(': ')}.join(', ')
|
94
94
|
inspected_constraints.prepend ' ' if inspected_constraints.size > 0
|
95
95
|
"#<#{ self.class.name }<#{ model_name }>#{ inspected_constraints }>"
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
def to_parse
|
99
99
|
{}.with_indifferent_access.tap do |result|
|
100
100
|
result[:query] = { where: constraints[:where], className: model_name } if constraints[:where]
|
101
101
|
result[:key] = constraints[:keys] if constraints[:keys]
|
102
102
|
end
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
def uncache
|
106
106
|
super.tap do |criteria|
|
107
107
|
criteria.instance_variable_set(:@cache, nil)
|
108
108
|
end
|
109
109
|
end
|
110
|
-
|
110
|
+
|
111
111
|
def total_count
|
112
112
|
count && variables[:total_count]
|
113
113
|
end
|
114
|
-
|
114
|
+
|
115
|
+
alias_method :size, :total_count
|
115
116
|
alias_method :to_ary, :to_a
|
116
|
-
|
117
|
+
|
117
118
|
private
|
118
|
-
|
119
|
+
|
119
120
|
def update_hash_value( hash_name, key, value )
|
120
121
|
hash = self.send( hash_name )
|
121
122
|
if hash[key].nil? || !value.is_a?(Hash)
|
@@ -126,4 +127,4 @@ module Opium
|
|
126
127
|
end
|
127
128
|
end
|
128
129
|
end
|
129
|
-
end
|
130
|
+
end
|
data/lib/opium/version.rb
CHANGED
@@ -6,10 +6,10 @@ describe Opium::Model::Criteria do
|
|
6
6
|
include Opium::Model
|
7
7
|
field :title, type: String
|
8
8
|
field :price, type: Float
|
9
|
-
|
9
|
+
|
10
10
|
stub('model_name').and_return(ActiveModel::Name.new(klass, nil, 'Game'))
|
11
11
|
end )
|
12
|
-
|
12
|
+
|
13
13
|
stub_request( :get, 'https://api.parse.com/1/classes/Game?count=1' ).with( body: {} ).
|
14
14
|
to_return( status: 200, headers: { 'Content-Type' => 'application/json' }, body: {
|
15
15
|
count: 10,
|
@@ -19,13 +19,13 @@ describe Opium::Model::Criteria do
|
|
19
19
|
]
|
20
20
|
}.to_json )
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
after do
|
24
24
|
Opium::Model::Criteria.models.clear
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
subject { Opium::Model::Criteria.new( 'Object' ) }
|
28
|
-
|
28
|
+
|
29
29
|
it { is_expected.to be_a( Opium::Model::Queryable::ClassMethods ) }
|
30
30
|
it { is_expected.to be_an( Enumerable ) }
|
31
31
|
it { is_expected.to respond_to( :chain ) }
|
@@ -37,9 +37,9 @@ describe Opium::Model::Criteria do
|
|
37
37
|
it { is_expected.to respond_to( :to_parse ) }
|
38
38
|
it { is_expected.to respond_to( :each ) }
|
39
39
|
it { is_expected.to respond_to( :to_a, :to_ary ) }
|
40
|
-
it { is_expected.to respond_to( :count, :total_count ) }
|
40
|
+
it { is_expected.to respond_to( :count, :total_count, :size ) }
|
41
41
|
it { is_expected.to respond_to( :to_partial_path ) }
|
42
|
-
|
42
|
+
|
43
43
|
describe '#chain' do
|
44
44
|
it 'returns a copy of the object' do
|
45
45
|
result = subject.chain
|
@@ -48,8 +48,8 @@ describe Opium::Model::Criteria do
|
|
48
48
|
result.should_not equal( subject )
|
49
49
|
end
|
50
50
|
end
|
51
|
-
|
52
|
-
describe '#update_constraint' do
|
51
|
+
|
52
|
+
describe '#update_constraint' do
|
53
53
|
it 'chains the criteria and alter the specified constraint on the copy' do
|
54
54
|
result = subject.update_constraint( :order, ['title', 1] )
|
55
55
|
result.should be_a( Opium::Model::Criteria )
|
@@ -58,20 +58,20 @@ describe Opium::Model::Criteria do
|
|
58
58
|
result.constraints.should have_key( :order )
|
59
59
|
result.constraints[:order].should == ['title', 1]
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
it 'merges hash-valued constraints' do
|
63
63
|
subject.constraints['where'] = { score: { '$lte' => 321 } }
|
64
64
|
result = subject.update_constraint( 'where', price: { '$gte' => 123 } )
|
65
65
|
result.constraints['where'].should =~ { 'score' => { '$lte' => 321 }, 'price' => { '$gte' => 123 } }
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
it 'deep merges hash-valued constraints' do
|
69
69
|
subject.constraints['where'] = { score: { '$lte' => 321 } }
|
70
70
|
result = subject.update_constraint( 'where', score: { '$gte' => 123 } )
|
71
71
|
result.constraints['where'].should =~ { 'score' => { '$lte' => 321, '$gte' => 123 } }
|
72
72
|
end
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
describe '#update_variable' do
|
76
76
|
it 'chains the criteria and alter the specified instance variable on the copy' do
|
77
77
|
result = subject.update_variable( :cache, true )
|
@@ -83,136 +83,136 @@ describe Opium::Model::Criteria do
|
|
83
83
|
result.variables[:cache].should == true
|
84
84
|
end
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
describe '#==' do
|
88
88
|
let( :first ) { Opium::Model::Criteria.new( 'Object' ).update_constraint( :order, ['title', 1] ) }
|
89
89
|
let( :second ) { Opium::Model::Criteria.new( 'Object' ).update_constraint( :order, ['title', 1] ) }
|
90
|
-
|
90
|
+
|
91
91
|
it 'should not affect :equal?' do
|
92
92
|
first.should_not equal( second )
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
it 'is based on the criteria constraints' do
|
96
96
|
first.should == second
|
97
97
|
end
|
98
|
-
|
98
|
+
|
99
99
|
it 'is based on the criteria variables' do
|
100
100
|
third = first.update_variable( :cache, true )
|
101
101
|
second.should_not == third
|
102
102
|
end
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
describe '#criteria' do
|
106
106
|
subject { Opium::Model::Criteria.new( 'Object' ).update_constraint( :order, ['title', 1] ) }
|
107
|
-
|
107
|
+
|
108
108
|
it 'is == to self' do
|
109
109
|
subject.criteria.should == subject
|
110
110
|
end
|
111
|
-
|
111
|
+
|
112
112
|
it 'is not a duplicate of self' do
|
113
113
|
subject.criteria.should equal( subject )
|
114
114
|
end
|
115
115
|
end
|
116
|
-
|
116
|
+
|
117
117
|
describe '#model' do
|
118
118
|
subject { Opium::Model::Criteria.new( 'Game' ) }
|
119
|
-
|
119
|
+
|
120
120
|
it 'is the constantized version of :model_name' do
|
121
121
|
subject.model_name.should == 'Game'
|
122
122
|
subject.model.should == Game
|
123
123
|
end
|
124
124
|
end
|
125
|
-
|
125
|
+
|
126
126
|
describe '#empty?' do
|
127
127
|
before do
|
128
128
|
stub_request(:get, "https://api.parse.com/1/classes/Game?count=1&where=%7B%22price%22:%7B%22$gte%22:9000.0%7D%7D").
|
129
129
|
to_return(
|
130
|
-
status: 200,
|
130
|
+
status: 200,
|
131
131
|
body: {
|
132
132
|
count: 0,
|
133
133
|
results: []
|
134
|
-
}.to_json,
|
134
|
+
}.to_json,
|
135
135
|
headers: { content_type: 'application/json' }
|
136
136
|
)
|
137
137
|
end
|
138
|
-
|
138
|
+
|
139
139
|
subject { Game.criteria }
|
140
|
-
|
140
|
+
|
141
141
|
it { expect { subject.empty? }.to_not raise_exception }
|
142
142
|
it do
|
143
143
|
expect( subject ).to receive(:count).once.and_call_original
|
144
144
|
subject.empty?
|
145
145
|
end
|
146
|
-
|
146
|
+
|
147
147
|
it 'returns true if count is 0' do
|
148
148
|
subject.gte( price: 9000.0 ).empty?.should == true
|
149
149
|
end
|
150
|
-
|
150
|
+
|
151
151
|
it 'returns false if count is not 0' do
|
152
152
|
subject.criteria.empty? == false
|
153
153
|
end
|
154
154
|
end
|
155
|
-
|
155
|
+
|
156
156
|
describe '#constraints?' do
|
157
157
|
it 'returns true if count is not the only constraint' do
|
158
158
|
Game.limit( 10 ).constraints?.should == true
|
159
159
|
end
|
160
|
-
|
160
|
+
|
161
161
|
it 'returns false if count is the only constraint' do
|
162
162
|
Game.criteria.constraints?.should == false
|
163
163
|
end
|
164
164
|
end
|
165
|
-
|
165
|
+
|
166
166
|
describe '#each' do
|
167
167
|
subject { Game.criteria }
|
168
|
-
|
168
|
+
|
169
169
|
context 'without a block' do
|
170
170
|
it 'returns an Enumerator' do
|
171
171
|
subject.each.should be_a( Enumerator )
|
172
172
|
end
|
173
173
|
end
|
174
|
-
|
174
|
+
|
175
175
|
context 'with a block' do
|
176
176
|
it "calls its :model's :http_get" do
|
177
177
|
subject.model.should receive(:http_get).with(query: subject.constraints)
|
178
178
|
subject.each {|model| }
|
179
179
|
end
|
180
|
-
|
180
|
+
|
181
181
|
it 'yields to its block any results it finds' do
|
182
182
|
expect {|b| subject.each &b }.to yield_control.twice
|
183
183
|
end
|
184
|
-
|
184
|
+
|
185
185
|
it 'yields to its block Opium::Model objects (Game in context)' do
|
186
186
|
expect {|b| subject.each &b }.to yield_successive_args(Opium::Model, Opium::Model)
|
187
187
|
expect {|b| subject.each &b }.to yield_successive_args(Game, Game)
|
188
188
|
end
|
189
|
-
|
189
|
+
|
190
190
|
it "calls its :model's :http_get when counting" do
|
191
191
|
subject.model.should receive(:http_get).with(query: subject.constraints).twice
|
192
192
|
subject.each {|model| }
|
193
193
|
subject.each.count
|
194
194
|
end
|
195
195
|
end
|
196
|
-
|
196
|
+
|
197
197
|
context 'when #cached?' do
|
198
198
|
subject { Game.criteria.cache }
|
199
|
-
|
199
|
+
|
200
200
|
it 'calls its :model\'s :http_get only once' do
|
201
201
|
subject.model.should receive(:http_get).with(query: subject.constraints).once
|
202
202
|
subject.each {|model| }
|
203
203
|
subject.each {|model| }
|
204
204
|
end
|
205
|
-
|
205
|
+
|
206
206
|
it 'yields to its block any results it finds' do
|
207
207
|
expect {|b| subject.each &b }.to yield_control.twice
|
208
208
|
expect {|b| subject.each &b }.to yield_control.twice
|
209
209
|
end
|
210
|
-
|
210
|
+
|
211
211
|
it 'yields to its block Opium::Model objects (Game in context)' do
|
212
212
|
expect {|b| subject.each &b }.to yield_successive_args(Opium::Model, Opium::Model)
|
213
213
|
expect {|b| subject.each &b }.to yield_successive_args(Game, Game)
|
214
214
|
end
|
215
|
-
|
215
|
+
|
216
216
|
it "does not call its :model's :http_get when counting" do
|
217
217
|
subject.model.should receive(:http_get).with(query: subject.constraints).once
|
218
218
|
subject.each {|model| }
|
@@ -220,62 +220,76 @@ describe Opium::Model::Criteria do
|
|
220
220
|
end
|
221
221
|
end
|
222
222
|
end
|
223
|
-
|
223
|
+
|
224
224
|
describe '#uncache' do
|
225
225
|
subject { Game.criteria.cache }
|
226
|
-
|
226
|
+
|
227
227
|
it 'causes #each to call its :model\'s :http_get twice' do
|
228
228
|
subject.model.should receive(:http_get).with(query: subject.constraints).twice
|
229
229
|
subject.each {|model| }
|
230
230
|
subject.uncache.each {|model| }
|
231
231
|
end
|
232
|
-
|
232
|
+
|
233
233
|
it 'deletes its @cache' do
|
234
234
|
subject.each {|model| }
|
235
235
|
subject.uncache.instance_variable_get(:@cache).should be_nil
|
236
236
|
end
|
237
237
|
end
|
238
|
-
|
238
|
+
|
239
239
|
describe '#count' do
|
240
240
|
subject { Game.criteria }
|
241
|
-
|
241
|
+
|
242
242
|
it { expect { subject.count }.to_not raise_exception }
|
243
243
|
it do
|
244
244
|
expect( subject ).to receive(:each).and_call_original
|
245
245
|
subject.count
|
246
246
|
end
|
247
|
-
|
247
|
+
|
248
248
|
it 'equals the number of items from #each' do
|
249
249
|
expect( subject.count ).to be == 2
|
250
250
|
end
|
251
251
|
end
|
252
|
-
|
252
|
+
|
253
253
|
describe '#total_count' do
|
254
254
|
subject { Game.criteria }
|
255
|
-
|
255
|
+
|
256
256
|
it { expect { subject.total_count }.to_not raise_exception }
|
257
257
|
it do
|
258
258
|
expect( subject ).to receive(:each).and_call_original
|
259
259
|
subject.total_count
|
260
260
|
end
|
261
|
-
|
261
|
+
|
262
262
|
it "equals the 'count' result returned from parse" do
|
263
263
|
expect( subject.total_count ).to be == 10
|
264
264
|
end
|
265
265
|
end
|
266
|
-
|
266
|
+
|
267
|
+
describe '#size' do
|
268
|
+
subject { Game.criteria }
|
269
|
+
|
270
|
+
it { expect { subject.size }.to_not raise_exception }
|
271
|
+
it do
|
272
|
+
expect( subject ).to receive(:each).and_call_original
|
273
|
+
subject.size
|
274
|
+
end
|
275
|
+
|
276
|
+
it "equals the 'count' result returned from parse" do
|
277
|
+
expect( subject.size ).to be == 10
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
267
281
|
describe '#to_parse' do
|
268
282
|
subject { Game.criteria }
|
269
|
-
|
283
|
+
|
270
284
|
it { expect( subject.to_parse ).to be_a( Hash ) }
|
271
|
-
|
285
|
+
|
272
286
|
it 'has a "query" key, if a "where" constraint exists, containing a "where" and a "className"' do
|
273
287
|
Game.between( price: 5..10 ).to_parse.tap do |criteria|
|
274
288
|
criteria.should have_key( 'query' )
|
275
289
|
criteria['query'].should =~ { 'where' => { 'price' => { '$gte' => 5, '$lte' => 10 } }, 'className' => 'Game' }
|
276
290
|
end
|
277
291
|
end
|
278
|
-
|
292
|
+
|
279
293
|
it 'should have a "key" key, if a "keys" constraint exists' do
|
280
294
|
Game.keys( :price ).to_parse.tap do |criteria|
|
281
295
|
criteria.should have_key( 'key' )
|
@@ -283,14 +297,14 @@ describe Opium::Model::Criteria do
|
|
283
297
|
end
|
284
298
|
end
|
285
299
|
end
|
286
|
-
|
300
|
+
|
287
301
|
describe '#to_partial_path' do
|
288
302
|
subject { Game.criteria }
|
289
|
-
|
303
|
+
|
290
304
|
it { expect { subject.to_partial_path }.to_not raise_exception }
|
291
|
-
|
305
|
+
|
292
306
|
it 'comes from the model class' do
|
293
307
|
expect( subject.to_partial_path ).to eq 'games/game'
|
294
308
|
end
|
295
309
|
end
|
296
|
-
end
|
310
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Bowers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|