PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/spec/examples/model/scope_spec.rb

https://github.com/fairfaxmedia/cequel
Ruby | 676 lines | 553 code | 123 blank | 0 comment | 34 complexity | a7116fa5d29781e4d2bd5fc67ec21951 MD5 | raw file
  1. require File.expand_path('../spec_helper', __FILE__)
  2. describe Cequel::Model::Scope do
  3. describe '#each' do
  4. it 'should provide enumerator for query results' do
  5. connection.stub(:execute).with("SELECT * FROM posts").
  6. and_return result_stub(:id => 1, :title => 'Cequel')
  7. Post.all.map { |post| [post.id, post.title] }.
  8. should == [[1, 'Cequel']]
  9. end
  10. it 'should enumerate results for just id if no key restriction' do
  11. connection.stub(:execute).with("SELECT ? FROM posts", [:id]).
  12. and_return result_stub(:id => 1)
  13. Post.select(:id).to_a.map { |post| post.id }.should == [1]
  14. end
  15. it 'should not enumerate results for just id if key restriction' do
  16. connection.stub(:execute).with("SELECT * FROM posts").
  17. and_return result_stub(:id => 1)
  18. Post.all.to_a.map { |post| post.id }.should == []
  19. end
  20. it 'should provide enumerator if no block given' do
  21. enum = Post.all.each
  22. connection.stub(:execute).with("SELECT * FROM posts").
  23. and_return result_stub(:id => 1, :title => 'Cequel')
  24. enum.map { |post| post.title }.should == ['Cequel']
  25. end
  26. it 'should enumerate zero times if empty-collection key restriction given' do
  27. Post.where(:id => []).to_a.should == []
  28. end
  29. it 'should enumerate zero times if empty-collection restriction given' do
  30. Post.where(:title => []).to_a.should == []
  31. end
  32. end
  33. describe '#first' do
  34. it 'should query for a single post' do
  35. connection.stub(:execute).with("SELECT * FROM posts LIMIT 1").
  36. and_return result_stub(:id => 1, :title => 'Cequel')
  37. Post.first.title.should == 'Cequel'
  38. end
  39. it 'should query for a single post within scope' do
  40. connection.stub(:execute).with("SELECT ? FROM posts LIMIT 1", [:id, :title]).
  41. and_return result_stub(:id => 1, :title => 'Cequel')
  42. Post.select(:id, :title).first.title.should == 'Cequel'
  43. end
  44. it 'should query scopes successively when multi-valued non-key column selected' do
  45. connection.stub(:execute).with("SELECT * FROM posts WHERE ? = ? LIMIT 1", :title, 'Cequel').
  46. and_return result_stub
  47. connection.stub(:execute).with("SELECT * FROM posts WHERE ? = ? LIMIT 1", :title, 'Cassandra').
  48. and_return result_stub(:id => 1, :title => 'Cassandra')
  49. connection.stub(:execute).with("SELECT * FROM posts WHERE ? = ? LIMIT 1", :title, 'CQL').
  50. and_return result_stub(:id => 2, :title => 'CQL')
  51. Post.where(:title => %w(Cequel Cassandra CQL)).first.title.
  52. should == 'Cassandra'
  53. end
  54. it 'should apply index preference when specified' do
  55. connection.should_receive(:execute).
  56. with("SELECT * FROM assets WHERE ? = ? AND ? = ? LIMIT 1", :checksum, 'abcdef', :class_name, 'Photo').
  57. and_return result_stub
  58. Photo.where(:checksum => 'abcdef').first
  59. end
  60. it 'should return nil when empty key collection given' do
  61. Post.where(:id => []).first.should be_nil
  62. end
  63. it 'should return nil when empty non-key collection given' do
  64. Post.where(:title => []).first.should be_nil
  65. end
  66. end
  67. describe '#count' do
  68. it 'should count records' do
  69. connection.stub(:execute).and_return count_result_stub(5)
  70. Post.count.should == 5
  71. end
  72. it 'should count records in scope' do
  73. connection.stub(:execute).
  74. with("SELECT COUNT(*) FROM posts WHERE ? = ?", :blog_id, 1).
  75. and_return count_result_stub(5)
  76. Post.where(:blog_id => 1).count.should == 5
  77. end
  78. it 'should raise error if attempting count with key restriction' do
  79. expect { Post.where(:id => [1, 2, 3]).count }.
  80. to raise_error(Cequel::Model::InvalidQuery)
  81. end
  82. it 'should perform multiple COUNT queries if non-key column selected for multiple values' do
  83. connection.stub(:execute).
  84. with("SELECT COUNT(*) FROM posts WHERE ? = ?", :blog_id, 1).
  85. and_return count_result_stub(3)
  86. connection.stub(:execute).
  87. with("SELECT COUNT(*) FROM posts WHERE ? = ?", :blog_id, 2).
  88. and_return count_result_stub(2)
  89. Post.where(:blog_id => [1, 2]).count.should == 5
  90. end
  91. it 'should return nil if empty non-key restriction given' do
  92. Post.where(:title => []).count.should == 0
  93. end
  94. it 'should apply index preference when specified' do
  95. connection.should_receive(:execute).
  96. with("SELECT COUNT(*) FROM assets WHERE ? = ? AND ? = ?", :checksum, 'abcdef', :class_name, 'Photo').
  97. and_return count_result_stub(0)
  98. Photo.where(:checksum => 'abcdef').count
  99. end
  100. end
  101. describe '#find' do
  102. it 'should send scoped query when no block is passed' do
  103. connection.stub(:execute).
  104. with("SELECT ? FROM posts WHERE ? = ? LIMIT 1", [:id, :title], :id, 1).
  105. and_return result_stub(:id => 1, :title => 'Cequel')
  106. Post.select(:id, :title).find(1).title.should == 'Cequel'
  107. end
  108. it 'should send scoped query with multiple keys when no block is passed' do
  109. connection.stub(:execute).
  110. with("SELECT ? FROM posts WHERE ? IN (?)", [:id, :title], :id, [1, 2]).
  111. and_return result_stub(
  112. {:id => 1, :title => 'Cequel'},
  113. {:id => 2, :title => 'Cequel 2'}
  114. )
  115. Post.select(:id, :title).find(1, 2).
  116. map { |post| post.title }.should == ['Cequel', 'Cequel 2']
  117. end
  118. it 'should delegate to enumerator when block is passed' do
  119. connection.stub(:execute).
  120. with("SELECT ? FROM posts", [:id, :title]).
  121. and_return result_stub(
  122. {:id => 1, :title => 'Cequel'},
  123. {:id => 2, :title => 'Cequel 2'}
  124. )
  125. Post.select(:id, :title).find { |post| post.id == 2 }.title.
  126. should == 'Cequel 2'
  127. end
  128. end
  129. describe '#any?' do
  130. it 'if called without block, should return true if COUNT > 0' do
  131. connection.stub(:execute).
  132. with("SELECT COUNT(*) FROM posts WHERE ? = ?", :blog_id, 1).
  133. and_return count_result_stub(5)
  134. Post.where(:blog_id => 1).any?.should be_true
  135. end
  136. it 'if called without block, should return false if COUNT == 0' do
  137. connection.stub(:execute).
  138. with("SELECT COUNT(*) FROM posts WHERE ? = ?", :blog_id, 1).
  139. and_return count_result_stub(0)
  140. Post.where(:blog_id => 1).any?.should be_false
  141. end
  142. it 'if called with block should delegate to enumerator' do
  143. connection.stub(:execute).
  144. with("SELECT * FROM posts WHERE ? = ?", :blog_id, 1).
  145. and_return result_stub(
  146. {:id => 1, :title => 'Cequel'},
  147. {:id => 2, :title => 'Cequel 2'}
  148. )
  149. Post.where(:blog_id => 1).any? { |post| post.id == 1 }.should be_true
  150. Post.where(:blog_id => 1).any? { |post| post.id == 8 }.should be_false
  151. end
  152. end
  153. describe '#none?' do
  154. it 'if called without block, should return false if COUNT > 0' do
  155. connection.stub(:execute).
  156. with("SELECT COUNT(*) FROM posts WHERE ? = ?", :blog_id, 1).
  157. and_return count_result_stub(5)
  158. Post.where(:blog_id => 1).none?.should be_false
  159. end
  160. it 'if called without block, should return true if COUNT == 0' do
  161. connection.stub(:execute).
  162. with("SELECT COUNT(*) FROM posts WHERE ? = ?", :blog_id, 1).
  163. and_return count_result_stub(0)
  164. Post.where(:blog_id => 1).none?.should be_true
  165. end
  166. it 'if called with block should delegate to enumerator' do
  167. connection.stub(:execute).
  168. with("SELECT * FROM posts WHERE ? = ?", :blog_id, 1).
  169. and_return result_stub(
  170. {:id => 1, :title => 'Cequel'},
  171. {:id => 2, :title => 'Cequel 2'}
  172. )
  173. Post.where(:blog_id => 1).none? { |post| post.id == 1 }.should be_false
  174. Post.where(:blog_id => 1).none? { |post| post.id == 8 }.should be_true
  175. end
  176. end
  177. describe '#one?' do
  178. it 'if called without block, should return false if COUNT == 0' do
  179. connection.stub(:execute).
  180. with("SELECT COUNT(*) FROM posts WHERE ? = ?", :blog_id, 1).
  181. and_return count_result_stub(0)
  182. Post.where(:blog_id => 1).one?.should be_false
  183. end
  184. it 'if called without block, should return true if COUNT == 1' do
  185. connection.stub(:execute).
  186. with("SELECT COUNT(*) FROM posts WHERE ? = ?", :blog_id, 1).
  187. and_return count_result_stub(1)
  188. Post.where(:blog_id => 1).one?.should be_true
  189. end
  190. it 'if called without block, should return false if COUNT > 1' do
  191. connection.stub(:execute).
  192. with("SELECT COUNT(*) FROM posts WHERE ? = ?", :blog_id, 1).
  193. and_return count_result_stub(12)
  194. Post.where(:blog_id => 1).one?.should be_false
  195. end
  196. it 'if called with block should delegate to enumerator' do
  197. connection.stub(:execute).
  198. with("SELECT * FROM posts WHERE ? = ?", :blog_id, 1).
  199. and_return result_stub(
  200. {:id => 1, :title => 'Cequel'},
  201. {:id => 2, :title => 'Cequel 2'}
  202. )
  203. Post.where(:blog_id => 1).none? { |post| post.id == 1 }.should be_false
  204. Post.where(:blog_id => 1).none? { |post| post.id == 8 }.should be_true
  205. end
  206. end
  207. describe '#find_in_batches' do
  208. it 'should select in batches of given size' do
  209. connection.stub(:execute).with("SELECT * FROM posts LIMIT 2").
  210. and_return result_stub(
  211. {:id => 1, :title => 'Post 1'},
  212. {:id => 2, :title => 'Post 2'}
  213. )
  214. connection.stub(:execute).
  215. with("SELECT * FROM posts WHERE ? > ? LIMIT 2", :id, 2).
  216. and_return result_stub(:id => 3, :title => 'Post 3')
  217. batches = []
  218. Post.find_in_batches(:batch_size => 2) do |batch|
  219. batches << batch
  220. end
  221. batches.map { |batch| batch.map(&:title) }.should ==
  222. [['Post 1', 'Post 2'], ['Post 3']]
  223. end
  224. it 'should not duplicate last key if given back first in next batch' do
  225. connection.stub(:execute).with("SELECT * FROM posts LIMIT 2").
  226. and_return result_stub(
  227. {:id => 1, :title => 'Post 1'},
  228. {:id => 2, :title => 'Post 2'}
  229. )
  230. connection.stub(:execute).
  231. with("SELECT * FROM posts WHERE ? > ? LIMIT 2", :id, 2).
  232. and_return result_stub(
  233. {:id => 2, :title => 'Post 2'},
  234. {:id => 3, :title => 'Post 3'}
  235. )
  236. connection.stub(:execute).
  237. with("SELECT * FROM posts WHERE ? > ? LIMIT 2", :id, 3).
  238. and_return result_stub()
  239. batches = []
  240. Post.find_in_batches(:batch_size => 2) do |batch|
  241. batches << batch
  242. end
  243. batches.map { |batch| batch.map(&:title) }.should ==
  244. [['Post 1', 'Post 2'], ['Post 3']]
  245. end
  246. it 'should iterate over batches of keys' do
  247. connection.stub(:execute).with("SELECT * FROM posts WHERE ? IN (?)", :id, [1, 2]).
  248. and_return result_stub(
  249. {:id => 1, :title => 'Post 1'},
  250. {:id => 2, :title => 'Post 2'}
  251. )
  252. connection.stub(:execute).
  253. with("SELECT * FROM posts WHERE ? = ?", :id, 3).
  254. and_return result_stub(:id => 3, :title => 'Post 3')
  255. batches = []
  256. Post.where(:id => [1, 2, 3]).find_in_batches(:batch_size => 2) do |batch|
  257. batches << batch
  258. end
  259. batches.map { |batch| batch.map(&:title) }.should ==
  260. [['Post 1', 'Post 2'], ['Post 3']]
  261. end
  262. it 'should respect scope' do
  263. connection.stub(:execute).with("SELECT ? FROM posts LIMIT 2", [:id, :title]).
  264. and_return result_stub(
  265. {:id => 1, :title => 'Post 1'},
  266. {:id => 2, :title => 'Post 2'}
  267. )
  268. connection.stub(:execute).
  269. with("SELECT ? FROM posts WHERE ? > ? LIMIT 2", [:id, :title], :id, 2).
  270. and_return result_stub(:id => 3, :title => 'Post 3')
  271. batches = []
  272. Post.select(:id, :title).find_in_batches(:batch_size => 2) do |batch|
  273. batches << batch
  274. end
  275. batches.map { |batch| batch.map(&:title) }.should ==
  276. [['Post 1', 'Post 2'], ['Post 3']]
  277. end
  278. it 'should add key column to SELECT if omitted' do
  279. connection.stub(:execute).with("SELECT ? FROM posts LIMIT 2", [:title, :id]).
  280. and_return result_stub(
  281. {:id => 1, :title => 'Post 1'},
  282. {:id => 2, :title => 'Post 2'}
  283. )
  284. connection.stub(:execute).
  285. with("SELECT ? FROM posts WHERE ? > ? LIMIT 2", [:title, :id], :id, 2).
  286. and_return result_stub(:id => 3, :title => 'Post 3')
  287. batches = []
  288. Post.select(:title).find_in_batches(:batch_size => 2) do |batch|
  289. batches << batch
  290. end
  291. batches.map { |batch| batch.map(&:title) }.should ==
  292. [['Post 1', 'Post 2'], ['Post 3']]
  293. end
  294. end
  295. describe '#find_each' do
  296. it 'should iterate over batches and yield results one by one' do
  297. connection.stub(:execute).with("SELECT * FROM posts LIMIT 2").
  298. and_return result_stub(
  299. {:id => 1, :title => 'Post 1'},
  300. {:id => 2, :title => 'Post 2'}
  301. )
  302. connection.stub(:execute).
  303. with("SELECT * FROM posts WHERE ? > ? LIMIT 2", :id, 2).
  304. and_return result_stub(:id => 3, :title => 'Post 3')
  305. Post.find_each(:batch_size => 2).map { |post| post.title }.
  306. should == ['Post 1', 'Post 2', 'Post 3']
  307. end
  308. end
  309. describe '#select' do
  310. it 'should scope columns in data set' do
  311. connection.stub(:execute).with("SELECT ? FROM posts", [:id, :title]).
  312. and_return result_stub(:id => 1, :title => 'Cequel')
  313. Post.select(:id, :title).map { |post| post.title }.should == ['Cequel']
  314. end
  315. it 'should fail fast if attempting to select only key column with restrictions on key column' do
  316. expect { Post.where(:id => 1).select(:id) }.
  317. to raise_error(Cequel::Model::InvalidQuery)
  318. end
  319. it 'should delegate to enumerator if block given' do
  320. connection.stub(:execute).
  321. with("SELECT * FROM posts WHERE ? = ?", :blog_id, 1).
  322. and_return result_stub(
  323. {:id => 1, :title => 'Cequel'},
  324. {:id => 2, :title => 'Cequel 2'},
  325. {:id => 3, :title => 'Cequel 3'}
  326. )
  327. Post.where(:blog_id => 1).select { |post| post.id < 3 }.
  328. map { |post| post.title }.should == ['Cequel', 'Cequel 2']
  329. end
  330. end
  331. describe '#select!' do
  332. it 'should override previous columns in data set' do
  333. connection.stub(:execute).with("SELECT ? FROM posts", [:id, :published]).
  334. and_return result_stub(:id => 1, :published => true)
  335. Post.select(:id, :title).select!(:id, :published).
  336. map { |post| post.published }.should == [true]
  337. end
  338. end
  339. describe '#consistency' do
  340. it 'should scope consistency in data set' do
  341. connection.stub(:execute).with("SELECT * FROM posts USING CONSISTENCY QUORUM").
  342. and_return result_stub(:id => 1, :title => 'Cequel')
  343. Post.consistency(:quorum).map { |post| post.title }.should == ['Cequel']
  344. end
  345. end
  346. describe '#where' do
  347. it 'should scope to row specifications in data set' do
  348. connection.stub(:execute).with("SELECT * FROM posts WHERE ? = ?", :id, 1).
  349. and_return result_stub(:id => 1, :title => 'Cequel')
  350. Post.where(:id => 1).map { |post| post.title }.should == ['Cequel']
  351. end
  352. it 'should perform multiple queries if IN query performed on non-key column' do
  353. connection.stub(:execute).with("SELECT * FROM posts WHERE ? = ?", :title, 'Cequel').
  354. and_return result_stub(:id => 1, :title => 'Cequel')
  355. connection.stub(:execute).with("SELECT * FROM posts WHERE ? = ?", :title, 'Fun').
  356. and_return result_stub(
  357. {:id => 2, :title => 'Fun'},
  358. {:id => 3, :title => 'Fun'}
  359. )
  360. Post.where(:title => %w(Cequel Fun)).map(&:id).
  361. should == [1, 2, 3]
  362. end
  363. it 'should fail fast if attempting to select only key column with restrictions on key column' do
  364. expect { Post.select(:id).where(:id => 1) }.
  365. to raise_error(Cequel::Model::InvalidQuery)
  366. end
  367. it 'should fail fast if attempting to mix key and non-key columns' do
  368. expect { Post.where(:id => 1).where(:title => 'Cequel') }.
  369. to raise_error(Cequel::Model::InvalidQuery)
  370. end
  371. it 'should use index preference if given' do
  372. connection.should_receive(:execute).
  373. with("SELECT * FROM assets WHERE ? = ? AND ? = ?", :checksum, 'abcdef', :class_name, 'Photo').
  374. and_return result_stub
  375. Photo.where(:checksum => 'abcdef').to_a
  376. end
  377. end
  378. describe '#where!' do
  379. it 'should override previously chained row specifications' do
  380. connection.stub(:execute).with("SELECT * FROM posts WHERE ? = ?", :title, 'Cequel').
  381. and_return result_stub(:id => 1, :title => 'Cequel')
  382. Post.where(:id => 1).where!(:title => 'Cequel').
  383. map { |post| post.title }.should == ['Cequel']
  384. end
  385. end
  386. describe '#limit' do
  387. it 'should limit results in data set' do
  388. connection.stub(:execute).with("SELECT * FROM posts LIMIT 5").
  389. and_return result_stub(:id => 1, :title => 'Cequel')
  390. Post.limit(5).map { |post| post.title }.should == ['Cequel']
  391. end
  392. end
  393. describe 'chaining' do
  394. it 'should aggregate scopes' do
  395. connection.stub(:execute).
  396. with("SELECT ? FROM posts USING CONSISTENCY QUORUM WHERE ? = ? LIMIT 5", [:id, :title], :blog_id, 1).
  397. and_return result_stub(:id => 1, :title => 'Cequel')
  398. Post.select(:id, :title).
  399. consistency(:quorum).
  400. where(:blog_id => 1).
  401. limit(5).
  402. map { |post| post.title }.should == ['Cequel']
  403. end
  404. it 'should delegate unknown methods to the underlying class with self as current scope' do
  405. connection.stub(:execute).
  406. with("SELECT ? FROM posts USING CONSISTENCY QUORUM WHERE ? = ? LIMIT 5", [:id, :title], :blog_id, 1).
  407. and_return result_stub(:id => 1, :title => 'Cequel')
  408. Post.select(:id, :title).
  409. consistency(:quorum).
  410. for_blog(1).
  411. limit(5).
  412. map { |post| post.title }.should == ['Cequel']
  413. end
  414. end
  415. describe '#update_all' do
  416. context 'with no scope restrictions' do
  417. let(:scope) { Post }
  418. it 'should get all keys and then update htem' do
  419. connection.should_receive(:execute).
  420. with("SELECT ? FROM posts", [:id]).
  421. and_return result_stub(
  422. {:id => 1},
  423. {:id => 2}
  424. )
  425. connection.should_receive(:execute).
  426. with "UPDATE posts SET ? = ? WHERE ? IN (?)", :title, 'Cequel', :id, [1, 2]
  427. scope.update_all(:title => 'Cequel')
  428. end
  429. end
  430. context 'with scope selecting on ids' do
  431. let(:scope) { Post.where(:id => [1, 2]) }
  432. it 'should issue scoped update request' do
  433. connection.should_receive(:execute).
  434. with "UPDATE posts SET ? = ? WHERE ? IN (?)", :title, 'Cequel', :id, [1, 2]
  435. scope.update_all(:title => 'Cequel')
  436. end
  437. end
  438. context 'with scope selecting on non-IDs' do
  439. let(:scope) { Post.where(:published => false) }
  440. it 'should perform "subquery" and issue update' do
  441. connection.stub(:execute).
  442. with("SELECT ? FROM posts WHERE ? = ?", [:id], :published, false).
  443. and_return result_stub({:id => 1}, {:id => 2})
  444. connection.should_receive(:execute).
  445. with "UPDATE posts SET ? = ? WHERE ? IN (?)", :title, 'Cequel', :id, [1, 2]
  446. scope.update_all(:title => 'Cequel')
  447. end
  448. end
  449. context 'with scope selecting multiple values on non-key column' do
  450. let(:scope) { Post.where(:title => %w(Cequel Cassandra)) }
  451. it 'should perform multiple subqueries and execute single update on returned keys' do
  452. connection.stub(:execute).
  453. with("SELECT ? FROM posts WHERE ? = ?", [:id], :title, 'Cequel').
  454. and_return result_stub({:id => 1}, {:id => 2})
  455. connection.stub(:execute).
  456. with("SELECT ? FROM posts WHERE ? = ?", [:id], :title, 'Cassandra').
  457. and_return result_stub({:id => 3}, {:id => 4})
  458. connection.should_receive(:execute).
  459. with "UPDATE posts SET ? = ? WHERE ? IN (?)", :published, true, :id, [1, 2, 3, 4]
  460. scope.update_all(:published => true)
  461. end
  462. end
  463. end
  464. describe '#destroy_all' do
  465. context 'with no scope restrictions' do
  466. let(:scope) { Post }
  467. it 'should destroy all instances' do
  468. connection.should_receive(:execute).
  469. with('SELECT * FROM posts').
  470. and_return result_stub(
  471. {'id' => 1, 'title' => 'Cequel'},
  472. {'id' => 2, 'title' => 'Cassandra'}
  473. )
  474. connection.should_receive(:execute).
  475. with "DELETE FROM posts WHERE ? = ?", :id, 1
  476. connection.should_receive(:execute).
  477. with "DELETE FROM posts WHERE ? = ?", :id, 2
  478. scope.destroy_all
  479. end
  480. end
  481. context 'with column restrictions' do
  482. let(:scope) { Post.where(:id => [1, 2]) }
  483. it 'should issue scoped update request' do
  484. connection.should_receive(:execute).
  485. with("SELECT * FROM posts WHERE ? IN (?)", :id, [1, 2]).
  486. and_return result_stub(
  487. {'id' => 1, 'title' => 'Cequel'},
  488. {'id' => 2, 'title' => 'Cassandra'}
  489. )
  490. connection.should_receive(:execute).
  491. with "DELETE FROM posts WHERE ? = ?", :id, 1
  492. connection.should_receive(:execute).
  493. with "DELETE FROM posts WHERE ? = ?", :id, 2
  494. scope.destroy_all
  495. end
  496. end
  497. end
  498. describe '#delete_all' do
  499. context 'with no scope restrictions' do
  500. let(:scope) { Post }
  501. it 'should truncate keyspace' do
  502. connection.should_receive(:execute).
  503. with "TRUNCATE posts"
  504. Post.delete_all
  505. end
  506. end
  507. context 'with scope selecting on ids' do
  508. let(:scope) { Post.where(:id => [1, 2]) }
  509. it 'should issue scoped delete request' do
  510. connection.should_receive(:execute).
  511. with "DELETE FROM posts WHERE ? IN (?)", :id, [1, 2]
  512. scope.delete_all
  513. end
  514. end
  515. context 'with scope selecting on non-IDs' do
  516. let(:scope) { Post.where(:published => false) }
  517. it 'should perform "subquery" and issue update' do
  518. connection.stub(:execute).
  519. with("SELECT ? FROM posts WHERE ? = ?", [:id], :published, false).
  520. and_return result_stub({:id => 1}, {:id => 2})
  521. connection.should_receive(:execute).
  522. with "DELETE FROM posts WHERE ? IN (?)", :id, [1, 2]
  523. scope.delete_all
  524. end
  525. end
  526. context 'with scope selecting multiple values on non-key column' do
  527. let(:scope) { Post.where(:title => %w(Cequel Cassandra)) }
  528. it 'should perform multiple subqueries and execute single update on returned keys' do
  529. connection.stub(:execute).
  530. with("SELECT ? FROM posts WHERE ? = ?", [:id], :title, 'Cequel').
  531. and_return result_stub({:id => 1}, {:id => 2})
  532. connection.stub(:execute).
  533. with("SELECT ? FROM posts WHERE ? = ?", [:id], :title, 'Cassandra').
  534. and_return result_stub({:id => 3}, {:id => 4})
  535. connection.should_receive(:execute).
  536. with "DELETE FROM posts WHERE ? IN (?)", :id, [1, 2, 3, 4]
  537. scope.delete_all
  538. end
  539. end
  540. end
  541. describe '::default_scope' do
  542. it 'should include in scope by default' do
  543. connection.should_receive(:execute).
  544. with("SELECT * FROM blogs LIMIT 100").and_return result_stub
  545. Blog.all.to_a
  546. end
  547. it 'should override as with normal scope' do
  548. connection.should_receive(:execute).
  549. with("SELECT * FROM blogs LIMIT 1000").and_return result_stub
  550. Blog.limit(1000).to_a
  551. end
  552. end
  553. end