PageRenderTime 52ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/test/functional/test_querying.rb

http://github.com/jnunemaker/mongomapper
Ruby | 898 lines | 861 code | 37 blank | 0 comment | 27 complexity | a05d15c4d3e5b23d973b1f232af4fcf3 MD5 | raw file
  1. require 'test_helper'
  2. class QueryingTesting < Test::Unit::TestCase
  3. def setup
  4. @document = Doc do
  5. key :first_name, String
  6. key :last_name, String
  7. key :age, Integer
  8. key :date, Date
  9. end
  10. end
  11. context ".query" do
  12. setup do
  13. @query = @document.query
  14. end
  15. should "set model to self" do
  16. @query.model.should == @document
  17. end
  18. should "always return new instance" do
  19. @document.query.should_not equal(@query)
  20. end
  21. should "apply options" do
  22. @document.query(:foo => 'bar')[:foo].should == 'bar'
  23. end
  24. end
  25. context ".criteria_hash" do
  26. setup do
  27. @hash = @document.criteria_hash
  28. end
  29. should "set object id keys on hash" do
  30. @hash.object_ids.should == [:_id]
  31. end
  32. should "always return new instance" do
  33. @document.criteria_hash.should_not equal(@hash)
  34. end
  35. should "apply provided criteria" do
  36. @document.criteria_hash(:foo => 'bar')[:foo].should == 'bar'
  37. end
  38. end
  39. context ".create (single document)" do
  40. setup do
  41. @doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  42. end
  43. should "create a document in correct collection" do
  44. @document.count.should == 1
  45. end
  46. should "automatically set id" do
  47. @doc.id.should be_instance_of(BSON::ObjectId)
  48. @doc._id.should be_instance_of(BSON::ObjectId)
  49. end
  50. should "no longer be new?" do
  51. @doc.new?.should be_false
  52. end
  53. should "return instance of document" do
  54. @doc.should be_instance_of(@document)
  55. @doc.first_name.should == 'John'
  56. @doc.last_name.should == 'Nunemaker'
  57. @doc.age.should == 27
  58. end
  59. should "not fail if no attributes provided" do
  60. document = Doc()
  61. lambda { document.create }.should change { document.count }.by(1)
  62. end
  63. end
  64. context ".create (multiple documents)" do
  65. setup do
  66. @docs = @document.create([
  67. {:first_name => 'John', :last_name => 'Nunemaker', :age => '27'},
  68. {:first_name => 'Steve', :last_name => 'Smith', :age => '28'},
  69. ])
  70. end
  71. should "create multiple documents" do
  72. @document.count.should == 2
  73. end
  74. should "return an array of doc instances" do
  75. @docs.map do |doc|
  76. doc.should be_instance_of(@document)
  77. end
  78. end
  79. end
  80. context ".update (single document)" do
  81. setup do
  82. doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  83. @doc = @document.update(doc._id, {:age => 40})
  84. end
  85. should "update attributes provided" do
  86. @doc.age.should == 40
  87. end
  88. should "not update existing attributes that were not set to update" do
  89. @doc.first_name.should == 'John'
  90. @doc.last_name.should == 'Nunemaker'
  91. end
  92. should "not create new document" do
  93. @document.count.should == 1
  94. end
  95. should "raise error if not provided id" do
  96. doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  97. lambda { @document.update }.should raise_error(ArgumentError)
  98. end
  99. should "raise error if not provided attributes" do
  100. doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  101. lambda { @document.update(doc._id) }.should raise_error(ArgumentError)
  102. lambda { @document.update(doc._id, [1]) }.should raise_error(ArgumentError)
  103. end
  104. end
  105. context ".update (multiple documents)" do
  106. setup do
  107. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  108. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  109. @docs = @document.update({
  110. @doc1._id => {:age => 30},
  111. @doc2._id => {:age => 30},
  112. })
  113. end
  114. should "not create any new documents" do
  115. @document.count.should == 2
  116. end
  117. should "should return an array of doc instances" do
  118. @docs.map do |doc|
  119. doc.should be_instance_of(@document)
  120. end
  121. end
  122. should "update the documents" do
  123. @document.find(@doc1._id).age.should == 30
  124. @document.find(@doc2._id).age.should == 30
  125. end
  126. should "raise error if not a hash" do
  127. lambda { @document.update([1, 2]) }.should raise_error(ArgumentError)
  128. end
  129. end
  130. context ".find" do
  131. setup do
  132. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  133. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  134. @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
  135. end
  136. should "return nil if nothing provided for find" do
  137. @document.find.should be_nil
  138. end
  139. should "raise document not found if nothing provided for find!" do
  140. assert_raises(MongoMapper::DocumentNotFound) do
  141. @document.find!
  142. end
  143. end
  144. context "(with a single id)" do
  145. should "work" do
  146. @document.find(@doc1._id).should == @doc1
  147. end
  148. should "return nil if document not found with find" do
  149. @document.find(123).should be_nil
  150. end
  151. should "raise error if document not found with find!" do
  152. assert_raises(MongoMapper::DocumentNotFound) { @document.find!(123) }
  153. end
  154. end
  155. context "(with multiple id's)" do
  156. should "work as arguments" do
  157. @document.find(@doc1._id, @doc2._id).should == [@doc1, @doc2]
  158. end
  159. should "work as arguments with string ids" do
  160. @document.find(@doc1._id.to_s, @doc2._id.to_s).should == [@doc1, @doc2]
  161. end
  162. should "work as array" do
  163. @document.find([@doc1._id, @doc2._id]).should == [@doc1, @doc2]
  164. end
  165. should "work as array with string ids" do
  166. @document.find([@doc1._id.to_s, @doc2._id.to_s]).should == [@doc1, @doc2]
  167. end
  168. should "compact not found when using find" do
  169. @document.find(@doc1._id, BSON::ObjectId.new.to_s).should == [@doc1]
  170. end
  171. should "raise error if not all found when using find!" do
  172. assert_raises(MongoMapper::DocumentNotFound) do
  173. @document.find!(@doc1._id, BSON::ObjectId.new.to_s)
  174. end
  175. end
  176. should "return array if array with one element" do
  177. @document.find([@doc1._id]).should == [@doc1]
  178. end
  179. end
  180. should "be able to find using condition auto-detection" do
  181. @document.first(:first_name => 'John').should == @doc1
  182. @document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
  183. end
  184. context "#all" do
  185. should "find all documents with options" do
  186. @document.all(:order => 'first_name').should == [@doc1, @doc3, @doc2]
  187. @document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
  188. end
  189. end
  190. context "#first" do
  191. should "find first document with options" do
  192. @document.first(:order => 'first_name').should == @doc1
  193. @document.first(:age => 28).should == @doc2
  194. end
  195. end
  196. context "#last" do
  197. should "find last document with options" do
  198. @document.last(:order => 'age').should == @doc2
  199. @document.last(:order => 'age', :age => 28).should == @doc2
  200. end
  201. end
  202. context "#find_each" do
  203. should "yield all documents found based on options" do
  204. yield_documents = []
  205. @document.find_each(:order => "first_name") {|doc| yield_documents << doc }
  206. yield_documents.should == [@doc1, @doc3, @doc2]
  207. yield_documents = []
  208. @document.find_each(:last_name => 'Nunemaker', :order => 'age desc') {|doc| yield_documents << doc }
  209. yield_documents.should == [@doc1, @doc3]
  210. end
  211. end
  212. end # finding documents
  213. context ".find_by_id" do
  214. setup do
  215. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  216. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  217. end
  218. should "be able to find by id" do
  219. @document.find_by_id(@doc1._id).should == @doc1
  220. @document.find_by_id(@doc2._id).should == @doc2
  221. end
  222. should "return nil if document not found" do
  223. @document.find_by_id(1234).should be_nil
  224. end
  225. end
  226. context ".first_or_create" do
  227. should "find if exists" do
  228. created = @document.create(:first_name => 'John', :last_name => 'Nunemaker')
  229. lambda {
  230. found = @document.first_or_create(:first_name => 'John', :last_name => 'Nunemaker')
  231. found.should == created
  232. }.should_not change { @document.count }
  233. end
  234. should "create if not found" do
  235. lambda {
  236. created = @document.first_or_create(:first_name => 'John', :last_name => 'Nunemaker')
  237. created.first_name.should == 'John'
  238. created.last_name.should == 'Nunemaker'
  239. }.should change { @document.count }.by(1)
  240. end
  241. should "disregard non-keys when creating, but use them in the query" do
  242. assert_nothing_raised do
  243. @document.create(:first_name => 'John', :age => 9)
  244. lambda {
  245. @document.first_or_create(:first_name => 'John', :age.gt => 10).first_name.should == 'John'
  246. }.should change { @document.count }.by(1)
  247. end
  248. end
  249. end
  250. context ".first_or_new" do
  251. should "find if exists" do
  252. created = @document.create(:first_name => 'John', :last_name => 'Nunemaker')
  253. lambda {
  254. found = @document.first_or_new(:first_name => 'John', :last_name => 'Nunemaker')
  255. found.should == created
  256. }.should_not change { @document.count }
  257. end
  258. should "initialize if not found" do
  259. lambda {
  260. created = @document.first_or_new(:first_name => 'John', :last_name => 'Nunemaker')
  261. created.first_name.should == 'John'
  262. created.last_name.should == 'Nunemaker'
  263. created.should be_new
  264. }.should_not change { @document.count }
  265. end
  266. should "disregard non-keys when initializing, but use them in the query" do
  267. assert_nothing_raised do
  268. @document.create(:first_name => 'John', :age => 9)
  269. @document.first_or_new(:first_name => 'John', :age.gt => 10).first_name.should == 'John'
  270. end
  271. end
  272. end
  273. context ".delete (single document)" do
  274. setup do
  275. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  276. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  277. @document.delete(@doc1._id)
  278. end
  279. should "remove document from collection" do
  280. @document.count.should == 1
  281. end
  282. should "not remove other documents" do
  283. @document.find(@doc2._id).should_not be(nil)
  284. end
  285. end
  286. context ".delete (multiple documents)" do
  287. should "work with multiple arguments" do
  288. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  289. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  290. @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
  291. @document.delete(@doc1._id, @doc2._id)
  292. @document.count.should == 1
  293. end
  294. should "work with array as argument" do
  295. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  296. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  297. @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
  298. @document.delete([@doc1._id, @doc2._id])
  299. @document.count.should == 1
  300. end
  301. end
  302. context ".delete_all" do
  303. setup do
  304. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  305. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  306. @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
  307. end
  308. should "remove all documents when given no conditions" do
  309. @document.delete_all
  310. @document.count.should == 0
  311. end
  312. should "only remove matching documents when given conditions" do
  313. @document.delete_all({:first_name => 'John'})
  314. @document.count.should == 2
  315. end
  316. should "convert the conditions to mongo criteria" do
  317. @document.delete_all(:age => [26, 27])
  318. @document.count.should == 1
  319. end
  320. end
  321. context ".destroy (single document)" do
  322. setup do
  323. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  324. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  325. @document.destroy(@doc1._id)
  326. end
  327. should "remove document from collection" do
  328. @document.count.should == 1
  329. end
  330. should "not remove other documents" do
  331. @document.find(@doc2._id).should_not be(nil)
  332. end
  333. end
  334. context ".destroy (multiple documents)" do
  335. should "work with multiple arguments" do
  336. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  337. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  338. @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
  339. @document.destroy(@doc1._id, @doc2._id)
  340. @document.count.should == 1
  341. end
  342. should "work with array as argument" do
  343. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  344. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  345. @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
  346. @document.destroy([@doc1._id, @doc2._id])
  347. @document.count.should == 1
  348. end
  349. end
  350. context ".destroy_all" do
  351. setup do
  352. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  353. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  354. @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
  355. end
  356. should "remove all documents when given no conditions" do
  357. @document.destroy_all
  358. @document.count.should == 0
  359. end
  360. should "only remove matching documents when given conditions" do
  361. @document.destroy_all(:first_name => 'John')
  362. @document.count.should == 2
  363. @document.destroy_all(:age => 26)
  364. @document.count.should == 1
  365. end
  366. should "convert the conditions to mongo criteria" do
  367. @document.destroy_all(:age => [26, 27])
  368. @document.count.should == 1
  369. end
  370. end
  371. context ".count" do
  372. setup do
  373. @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
  374. @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
  375. @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
  376. end
  377. should "count all with no arguments" do
  378. @document.count.should == 3
  379. end
  380. should "return 0 if there are no documents in the collection" do
  381. @document.delete_all
  382. @document.count.should == 0
  383. end
  384. should "return 0 if the collection does not exist" do
  385. klass = Doc do
  386. set_collection_name 'foobarbazwickdoesnotexist'
  387. end
  388. klass.count.should == 0
  389. end
  390. should "return count for matching documents if conditions provided" do
  391. @document.count(:age => 27).should == 1
  392. end
  393. should "convert the conditions to mongo criteria" do
  394. @document.count(:age => [26, 27]).should == 2
  395. end
  396. end
  397. context ".exists?" do
  398. setup do
  399. @doc = @document.create(:first_name => "James", :age => 27)
  400. end
  401. should "be true when at least one document exists" do
  402. @document.exists?.should == true
  403. end
  404. should "be false when no documents exist" do
  405. @doc.destroy
  406. @document.exists?.should == false
  407. end
  408. should "be true when at least one document exists that matches the conditions" do
  409. @document.exists?(:first_name => "James").should == true
  410. end
  411. should "be false when no documents exist with the provided conditions" do
  412. @document.exists?(:first_name => "Jean").should == false
  413. end
  414. end
  415. context ".where" do
  416. setup do
  417. @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
  418. @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
  419. @doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
  420. @query = @document.where(:last_name => 'Nunemaker')
  421. end
  422. should "fetch documents when kicker called" do
  423. docs = @query.all
  424. docs.should include(@doc1)
  425. docs.should include(@doc3)
  426. docs.should_not include(@doc2)
  427. end
  428. should "be chainable" do
  429. @query.sort(:age).first.should == @doc3
  430. end
  431. end
  432. context ".fields" do
  433. setup do
  434. @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
  435. @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
  436. @doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
  437. @query = @document.fields(:age)
  438. end
  439. should "fetch documents when kicker called" do
  440. docs = @query.all
  441. docs.should include(@doc1)
  442. docs.should include(@doc3)
  443. docs.should include(@doc2)
  444. docs.each do |doc|
  445. doc.age.should_not be_nil
  446. doc.first_name.should be_nil # key was not loaded
  447. doc.last_name.should be_nil # key was not loaded
  448. end
  449. end
  450. should "be chainable" do
  451. @query.sort(:age).all.map(&:age).should == [26, 27, 28]
  452. end
  453. end
  454. context ".limit" do
  455. setup do
  456. @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
  457. @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
  458. @doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
  459. @query = @document.limit(2)
  460. end
  461. should "fetch documents when kicker called" do
  462. docs = @query.all
  463. docs.size.should == 2
  464. end
  465. should "be chainable" do
  466. result = [26, 27]
  467. @query.sort(:age).all.map(&:age).should == result
  468. @query.count.should > result.size
  469. end
  470. end
  471. context ".skip" do
  472. setup do
  473. @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
  474. @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
  475. @doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
  476. @query = @document.skip(1)
  477. end
  478. should "fetch documents when kicker called" do
  479. docs = @query.all
  480. docs.size.should == 2 # skipping 1 out of 3
  481. end
  482. should "be chainable" do
  483. result = [27, 28]
  484. @query.sort(:age).all.map(&:age).should == result
  485. @query.count.should > result.size
  486. end
  487. end
  488. context ".sort" do
  489. setup do
  490. @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
  491. @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
  492. @doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
  493. @query = @document.sort(:age)
  494. end
  495. should "fetch documents when kicker called" do
  496. @query.all.should == [@doc3, @doc1, @doc2]
  497. end
  498. should "be chainable" do
  499. result = [28]
  500. @query.skip(2).all.map(&:age).should == result
  501. @query.count.should > result.size
  502. end
  503. end
  504. context "#update_attributes (new document)" do
  505. setup do
  506. @doc = @document.new(:first_name => 'John', :age => '27')
  507. @doc.update_attributes(:first_name => 'Johnny', :age => 30)
  508. end
  509. should "insert document into the collection" do
  510. @document.count.should == 1
  511. end
  512. should "assign an id for the document" do
  513. @doc.id.should be_instance_of(BSON::ObjectId)
  514. end
  515. should "save attributes" do
  516. @doc.first_name.should == 'Johnny'
  517. @doc.age.should == 30
  518. end
  519. should "update attributes in the database" do
  520. doc = @doc.reload
  521. doc.should == @doc
  522. doc.first_name.should == 'Johnny'
  523. doc.age.should == 30
  524. end
  525. should "allow updating custom attributes" do
  526. @doc.update_attributes(:gender => 'mALe')
  527. @doc.reload.gender.should == 'mALe'
  528. end
  529. end
  530. context "#update_attributes (existing document)" do
  531. setup do
  532. @doc = @document.create(:first_name => 'John', :age => '27')
  533. @doc.update_attributes(:first_name => 'Johnny', :age => 30)
  534. end
  535. should "not insert document into collection" do
  536. @document.count.should == 1
  537. end
  538. should "update attributes" do
  539. @doc.first_name.should == 'Johnny'
  540. @doc.age.should == 30
  541. end
  542. should "update attributes in the database" do
  543. doc = @doc.reload
  544. doc.first_name.should == 'Johnny'
  545. doc.age.should == 30
  546. end
  547. end
  548. context "#update_attributes (return value)" do
  549. setup do
  550. @document.key :foo, String, :required => true
  551. end
  552. should "be true if document valid" do
  553. @document.new.update_attributes(:foo => 'bar').should be_true
  554. end
  555. should "be false if document not valid" do
  556. @document.new.update_attributes({}).should be_false
  557. end
  558. end
  559. context "#update_attribute" do
  560. setup do
  561. @doc = @document.create(:first_name => 'John', :age => '27')
  562. end
  563. should "accept symbols as keys" do
  564. @doc.update_attribute(:first_name, 'Chris').should be_true
  565. @doc.reload.first_name.should == 'Chris'
  566. end
  567. should "update the attribute" do
  568. @doc.update_attribute('first_name', 'Chris').should be_true
  569. @doc.reload.first_name.should == 'Chris'
  570. end
  571. should "update the attribute without invoking validations" do
  572. @document.key :name, String, :required => true
  573. @doc.expects(:valid?).never
  574. @doc.update_attribute('name', '').should be_true
  575. @doc.reload.name.should == ''
  576. @document.count.should == 1
  577. end
  578. end
  579. context "#save (new document)" do
  580. setup do
  581. @doc = @document.new(:first_name => 'John', :age => '27')
  582. @doc.save
  583. end
  584. should "insert document into the collection" do
  585. @document.count.should == 1
  586. end
  587. should "assign an id for the document" do
  588. @doc.id.should be_instance_of(BSON::ObjectId)
  589. end
  590. should "save attributes" do
  591. @doc.first_name.should == 'John'
  592. @doc.age.should == 27
  593. end
  594. should "update attributes in the database" do
  595. doc = @doc.reload
  596. doc.should == @doc
  597. doc.first_name.should == 'John'
  598. doc.age.should == 27
  599. end
  600. should "allow to add custom attributes to the document" do
  601. @doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male', :tags => [1, "2"])
  602. @doc.save
  603. doc = @doc.reload
  604. doc.gender.should == 'male'
  605. doc.tags.should == [1, "2"]
  606. end
  607. should "allow to use custom methods to assign properties" do
  608. klass = Doc do
  609. key :name, String
  610. def realname=(value)
  611. self.name = value
  612. end
  613. end
  614. person = klass.new(:realname => 'David')
  615. person.save
  616. person.reload.name.should == 'David'
  617. end
  618. context "with key of type date" do
  619. should "save the date value as a Time object" do
  620. doc = @document.new(:first_name => 'John', :age => '27', :date => "2009-12-01")
  621. doc.save
  622. doc.date.should == Date.new(2009, 12, 1)
  623. end
  624. end
  625. end
  626. context "#save (existing document)" do
  627. setup do
  628. @doc = @document.create(:first_name => 'John', :age => '27')
  629. @doc.first_name = 'Johnny'
  630. @doc.age = 30
  631. @doc.save
  632. end
  633. should "not insert document into collection" do
  634. @document.count.should == 1
  635. end
  636. should "update attributes" do
  637. @doc.first_name.should == 'Johnny'
  638. @doc.age.should == 30
  639. end
  640. should "update attributes in the database" do
  641. doc = @doc.reload
  642. doc.first_name.should == 'Johnny'
  643. doc.age.should == 30
  644. end
  645. should "allow updating custom attributes" do
  646. @doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male')
  647. @doc.gender = 'Male'
  648. @doc.save
  649. @doc.reload.gender.should == 'Male'
  650. end
  651. end
  652. context "#save (with validations off)" do
  653. setup do
  654. @document = Doc do
  655. key :name, String, :required => true
  656. end
  657. end
  658. should "insert invalid document" do
  659. doc = @document.new
  660. doc.expects(:valid?).never
  661. doc.save(:validate => false)
  662. @document.count.should == 1
  663. end
  664. end
  665. context "#save (with options)" do
  666. setup do
  667. @document = Doc do
  668. key :name, String
  669. end
  670. @document.ensure_index :name, :unique => true
  671. end
  672. teardown { drop_indexes(@document) }
  673. should "allow passing safe" do
  674. @document.create(:name => 'John')
  675. assert_raises(Mongo::OperationFailure) do
  676. @document.new(:name => 'John').save(:safe => true)
  677. end
  678. end
  679. should "raise argument error if options has unsupported key" do
  680. assert_raises(ArgumentError) do
  681. @document.new.save(:foo => true)
  682. end
  683. end
  684. end
  685. context "#save! (with options)" do
  686. setup do
  687. @document = Doc { key :name, String }
  688. @document.ensure_index :name, :unique => true
  689. end
  690. teardown { drop_indexes(@document) }
  691. should "allow passing safe" do
  692. @document.create(:name => 'John')
  693. assert_raises(Mongo::OperationFailure) do
  694. @document.new(:name => 'John').save!(:safe => true)
  695. end
  696. end
  697. should "raise argument error if options has unsupported key" do
  698. assert_raises(ArgumentError) do
  699. @document.new.save!(:foo => true)
  700. end
  701. end
  702. should "raise argument error if using validate as that would be pointless with save!" do
  703. assert_raises(ArgumentError) do
  704. @document.new.save!(:validate => false)
  705. end
  706. end
  707. end
  708. context "#destroy" do
  709. setup do
  710. @doc = @document.create(:first_name => 'John', :age => '27')
  711. @doc.destroy
  712. end
  713. should "remove the document from the collection" do
  714. @document.count.should == 0
  715. end
  716. end
  717. context "#delete" do
  718. setup do
  719. @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
  720. @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
  721. @document.class_eval do
  722. before_destroy :before_destroy_callback
  723. after_destroy :after_destroy_callback
  724. def history; @history ||= [] end
  725. def before_destroy_callback; history << :after_destroy end
  726. def after_destroy_callback; history << :after_destroy end
  727. end
  728. @doc1.delete
  729. end
  730. should "remove document from collection" do
  731. @document.count.should == 1
  732. end
  733. should "not remove other documents" do
  734. @document.find(@doc2.id).should_not be(nil)
  735. end
  736. should "not call before/after destroy callbacks" do
  737. @doc1.history.should == []
  738. end
  739. end
  740. end