Skip to content

Commit 8bf372e

Browse files
committed
Don’t allow re-assign Chain’s query manually
1 parent 2fb34f0 commit 8bf372e

File tree

3 files changed

+35
-38
lines changed

3 files changed

+35
-38
lines changed

lib/dynamoid/criteria/chain.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ module Criteria
55
# The criteria chain is equivalent to an ActiveRecord relation (and realistically I should change the name from
66
# chain to relation). It is a chainable object that builds up a query and eventually executes it by a Query or Scan.
77
class Chain
8-
attr_accessor :query, :source, :values, :consistent_read
98
attr_reader :hash_key, :range_key, :index_name
9+
attr_reader :query, :source, :consistent_read
1010
include Enumerable
1111
# Create a new criteria chain.
1212
#

lib/dynamoid/finders.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ def method_missing(method, *args)
264264
attributes = method.to_s.split('_by_').last.split('_and_')
265265

266266
chain = Dynamoid::Criteria::Chain.new(self)
267-
chain.query = {}.tap { |h| attributes.each_with_index { |attr, index| h[attr.to_sym] = args[index] } }
267+
chain = chain.where({}.tap { |h| attributes.each_with_index { |attr, index| h[attr.to_sym] = args[index] } })
268268

269269
if finder =~ /all/
270270
return chain.all

spec/dynamoid/criteria/chain_spec.rb

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,42 +10,42 @@
1010
describe 'Query vs Scan' do
1111
it 'Scans when query is empty' do
1212
chain = Dynamoid::Criteria::Chain.new(Address)
13-
chain.query = {}
13+
chain = chain.where({})
1414
expect(chain).to receive(:pages_via_scan).and_return([])
1515
chain.all
1616
end
1717

1818
it 'Queries when query is only ID' do
1919
chain = Dynamoid::Criteria::Chain.new(Address)
20-
chain.query = { id: 'test' }
20+
chain = chain.where(id: 'test')
2121
expect(chain).to receive(:pages_via_query).and_return([])
2222
chain.all
2323
end
2424

2525
it 'Queries when query contains ID' do
2626
chain = Dynamoid::Criteria::Chain.new(Address)
27-
chain.query = { id: 'test', city: 'Bucharest' }
27+
chain = chain.where(id: 'test', city: 'Bucharest')
2828
expect(chain).to receive(:pages_via_query).and_return([])
2929
chain.all
3030
end
3131

3232
it 'Scans when query includes keys that are neither a hash nor a range' do
3333
chain = Dynamoid::Criteria::Chain.new(Address)
34-
chain.query = { city: 'Bucharest' }
34+
chain = chain.where(city: 'Bucharest')
3535
expect(chain).to receive(:pages_via_scan).and_return([])
3636
chain.all
3737
end
3838

3939
it 'Scans when query is only a range' do
4040
chain = Dynamoid::Criteria::Chain.new(Tweet)
41-
chain.query = { group: 'xx' }
41+
chain = chain.where(group: 'xx')
4242
expect(chain).to receive(:pages_via_scan).and_return([])
4343
chain.all
4444
end
4545

4646
it 'Scans when there is only not-equal operator for hash key' do
4747
chain = Dynamoid::Criteria::Chain.new(Address)
48-
chain.query = { 'id.in': ['test'] }
48+
chain = chain.where('id.in': ['test'])
4949
expect(chain).to receive(:pages_via_scan).and_return([])
5050
chain.all
5151
end
@@ -1092,7 +1092,7 @@ def request_params
10921092
document3 = klass.create!(title: 'Doc #3')
10931093

10941094
chain = Dynamoid::Criteria::Chain.new(klass)
1095-
chain.query = { title: 'Doc #2' }
1095+
chain = chain.where(title: 'Doc #2')
10961096

10971097
expect { chain.delete_all }.to change { klass.count }.by(-1)
10981098
expect(klass.all).to contain_exactly(document1, document3)
@@ -1106,7 +1106,7 @@ def request_params
11061106
document = klass.create!(title: 'Doc #1')
11071107

11081108
chain = Dynamoid::Criteria::Chain.new(klass)
1109-
chain.query = { id: document.id }
1109+
chain = chain.where(id: document.id)
11101110

11111111
expect(Dynamoid.adapter.client).to receive(:query).and_call_original
11121112
expect { chain.delete_all }.to change { klass.count }.by(-1)
@@ -1121,7 +1121,7 @@ def request_params
11211121
klass.create!(title: "The Cuckoo's Calling", author: 'J. K. Rowling')
11221122

11231123
chain = Dynamoid::Criteria::Chain.new(klass)
1124-
chain.query = { author: 'J. K. Rowling' }
1124+
chain = chain.where(author: 'J. K. Rowling')
11251125

11261126
expect(Dynamoid.adapter.client).to receive(:scan).and_call_original
11271127
expect { chain.delete_all }.to change { klass.count }.by(-1)
@@ -1137,7 +1137,7 @@ def request_params
11371137
klass.create!(title: 'Doc #2')
11381138

11391139
chain = Dynamoid::Criteria::Chain.new(klass)
1140-
chain.query = { id: document.id }
1140+
chain = chain.where(id: document.id)
11411141

11421142
expect { chain.delete_all }.to change { klass.count }.by(-1)
11431143
end
@@ -1151,7 +1151,7 @@ def request_params
11511151
klass.create!
11521152

11531153
chain = Dynamoid::Criteria::Chain.new(klass)
1154-
chain.query = { id: document.id }
1154+
chain = chain.where(id: document.id)
11551155

11561156
expect { chain.delete_all }.to change { klass.count }.by(-1)
11571157
end
@@ -1167,7 +1167,7 @@ def request_params
11671167
klass.create!(title: 'Doc #2')
11681168

11691169
chain = Dynamoid::Criteria::Chain.new(klass)
1170-
chain.query = { title: 'Doc #1' }
1170+
chain = chain.where(title: 'Doc #1')
11711171

11721172
expect { chain.delete_all }.to change { klass.count }.by(-1)
11731173
end
@@ -1181,7 +1181,7 @@ def request_params
11811181
klass.create!(title: 'Doc #2')
11821182

11831183
chain = Dynamoid::Criteria::Chain.new(klass)
1184-
chain.query = { title: 'Doc #1' }
1184+
chain = chain.where(title: 'Doc #1')
11851185

11861186
expect { chain.delete_all }.to change { klass.count }.by(-1)
11871187
end
@@ -1225,42 +1225,42 @@ def request_params
12251225
describe 'Query vs Scan' do
12261226
it 'Scans when query is empty' do
12271227
chain = Dynamoid::Criteria::Chain.new(Address)
1228-
chain.query = {}
1228+
chain = chain.where({})
12291229
expect(chain).to receive(:count_via_scan)
12301230
chain.count
12311231
end
12321232

12331233
it 'Queries when query is only ID' do
12341234
chain = Dynamoid::Criteria::Chain.new(Address)
1235-
chain.query = { id: 'test' }
1235+
chain = chain.where(id: 'test')
12361236
expect(chain).to receive(:count_via_query)
12371237
chain.count
12381238
end
12391239

12401240
it 'Queries when query contains ID' do
12411241
chain = Dynamoid::Criteria::Chain.new(Address)
1242-
chain.query = { id: 'test', city: 'Bucharest' }
1242+
chain = chain.where(id: 'test', city: 'Bucharest')
12431243
expect(chain).to receive(:count_via_query)
12441244
chain.count
12451245
end
12461246

12471247
it 'Scans when query includes keys that are neither a hash nor a range' do
12481248
chain = Dynamoid::Criteria::Chain.new(Address)
1249-
chain.query = { city: 'Bucharest' }
1249+
chain = chain.where(city: 'Bucharest')
12501250
expect(chain).to receive(:count_via_scan)
12511251
chain.count
12521252
end
12531253

12541254
it 'Scans when query is only a range' do
12551255
chain = Dynamoid::Criteria::Chain.new(Tweet)
1256-
chain.query = { group: 'xx' }
1256+
chain = chain.where(group: 'xx')
12571257
expect(chain).to receive(:count_via_scan)
12581258
chain.count
12591259
end
12601260

12611261
it 'Scans when there is only not-equal operator for hash key' do
12621262
chain = Dynamoid::Criteria::Chain.new(Address)
1263-
chain.query = { 'id.in': ['test'] }
1263+
chain = chain.where('id.in': ['test'])
12641264
expect(chain).to receive(:count_via_scan)
12651265
chain.count
12661266
end
@@ -1306,14 +1306,14 @@ def request_params
13061306
let(:chain) { described_class.new(User) }
13071307

13081308
it 'defines each' do
1309-
chain.query = { name: 'Josh' }
1309+
chain = self.chain.where(name: 'Josh')
13101310
chain.each { |u| u.update_attribute(:name, 'Justin') }
13111311

13121312
expect(User.find(user.id).name).to eq 'Justin'
13131313
end
13141314

13151315
it 'includes Enumerable' do
1316-
chain.query = { name: 'Josh' }
1316+
chain = self.chain.where(name: 'Josh')
13171317

13181318
expect(chain.collect(&:name)).to eq ['Josh']
13191319
end
@@ -1327,20 +1327,20 @@ def request_params
13271327
let(:chain) { Dynamoid::Criteria::Chain.new(Tweet) }
13281328

13291329
it 'limits evaluated records' do
1330-
chain.query = {}
1330+
chain = self.chain.where({})
13311331
expect(chain.record_limit(1).count).to eq 1
13321332
expect(chain.record_limit(2).count).to eq 2
13331333
end
13341334

13351335
it 'finds tweets with a start' do
1336-
chain.query = { tweet_id: 'x' }
1336+
chain = self.chain.where(tweet_id: 'x')
13371337
chain.start(tweet1)
13381338
expect(chain.count).to eq 1
13391339
expect(chain.first).to eq tweet2
13401340
end
13411341

13421342
it 'finds one specific tweet' do
1343-
chain.query = { tweet_id: 'xx', group: 'two' }
1343+
chain = self.chain.where(tweet_id: 'xx', group: 'two')
13441344
expect(chain.all.to_a).to eq [tweet3]
13451345
end
13461346

@@ -1350,10 +1350,9 @@ def request_params
13501350
post1 = Post.create(post_id: 'x', posted_at: time)
13511351
post2 = Post.create(post_id: 'x', posted_at: (time + 1.hour))
13521352
chain = Dynamoid::Criteria::Chain.new(Post)
1353-
query = { post_id: 'x', 'posted_at.gt': (time + ts_epsilon) }
1354-
resultset = chain.send(:where, query)
1355-
expect(resultset.count).to eq 1
1356-
stored_record = resultset.first
1353+
chain = chain.where(post_id: 'x', 'posted_at.gt': (time + ts_epsilon))
1354+
expect(chain.count).to eq 1
1355+
stored_record = chain.first
13571356
expect(stored_record.attributes[:post_id]).to eq post2.attributes[:post_id]
13581357
# Must use an epsilon to compare timestamps after round-trip: https://github.com/Dynamoid/Dynamoid/issues/2
13591358
expect(stored_record.attributes[:created_at]).to be_within(ts_epsilon).of(post2.attributes[:created_at])
@@ -1367,10 +1366,9 @@ def request_params
13671366
post1 = Post.create(post_id: 'x', posted_at: time)
13681367
post2 = Post.create(post_id: 'x', posted_at: (time + 1.hour))
13691368
chain = Dynamoid::Criteria::Chain.new(Post)
1370-
query = { post_id: 'x', 'posted_at.lt': (time + 1.hour - ts_epsilon) }
1371-
resultset = chain.send(:where, query)
1372-
expect(resultset.count).to eq 1
1373-
stored_record = resultset.first
1369+
chain = chain.where(post_id: 'x', 'posted_at.lt': (time + 1.hour - ts_epsilon) )
1370+
expect(chain.count).to eq 1
1371+
stored_record = chain.first
13741372
expect(stored_record.attributes[:post_id]).to eq post2.attributes[:post_id]
13751373
# Must use an epsilon to compare timestamps after round-trip: https://github.com/Dynamoid/Dynamoid/issues/2
13761374
expect(stored_record.attributes[:created_at]).to be_within(ts_epsilon).of(post1.attributes[:created_at])
@@ -1384,10 +1382,9 @@ def request_params
13841382
post1 = Post.create(post_id: 'x', posted_at: time)
13851383
post2 = Post.create(post_id: 'x', posted_at: (time + 1.hour))
13861384
chain = Dynamoid::Criteria::Chain.new(Post)
1387-
query = { post_id: 'x', 'posted_at.between': [time - ts_epsilon, time + ts_epsilon] }
1388-
resultset = chain.send(:where, query)
1389-
expect(resultset.count).to eq 1
1390-
stored_record = resultset.first
1385+
chain = chain.where(post_id: 'x', 'posted_at.between': [time - ts_epsilon, time + ts_epsilon])
1386+
expect(chain.count).to eq 1
1387+
stored_record = chain.first
13911388
expect(stored_record.attributes[:post_id]).to eq post2.attributes[:post_id]
13921389
# Must use an epsilon to compare timestamps after round-trip: https://github.com/Dynamoid/Dynamoid/issues/2
13931390
expect(stored_record.attributes[:created_at]).to be_within(ts_epsilon).of(post1.attributes[:created_at])

0 commit comments

Comments
 (0)