PageRenderTime 67ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/vendor/rails/activerecord/test/associations_test.rb

https://github.com/tolsen/limeberry
Ruby | 1839 lines | 1634 code | 194 blank | 11 comment | 2 complexity | 29a989ac2d4352d6c84c5ed13f07efd3 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. require 'abstract_unit'
  2. require 'fixtures/developer'
  3. require 'fixtures/project'
  4. require 'fixtures/company'
  5. require 'fixtures/topic'
  6. require 'fixtures/reply'
  7. require 'fixtures/computer'
  8. require 'fixtures/customer'
  9. require 'fixtures/order'
  10. require 'fixtures/categorization'
  11. require 'fixtures/category'
  12. require 'fixtures/post'
  13. require 'fixtures/author'
  14. require 'fixtures/comment'
  15. require 'fixtures/tag'
  16. require 'fixtures/tagging'
  17. class AssociationsTest < Test::Unit::TestCase
  18. fixtures :accounts, :companies, :developers, :projects, :developers_projects,
  19. :computers
  20. def test_bad_collection_keys
  21. assert_raise(ArgumentError, 'ActiveRecord should have barked on bad collection keys') do
  22. Class.new(ActiveRecord::Base).has_many(:wheels, :name => 'wheels')
  23. end
  24. end
  25. def test_force_reload
  26. firm = Firm.new("name" => "A New Firm, Inc")
  27. firm.save
  28. firm.clients.each {|c|} # forcing to load all clients
  29. assert firm.clients.empty?, "New firm shouldn't have client objects"
  30. assert_equal 0, firm.clients.size, "New firm should have 0 clients"
  31. client = Client.new("name" => "TheClient.com", "firm_id" => firm.id)
  32. client.save
  33. assert firm.clients.empty?, "New firm should have cached no client objects"
  34. assert_equal 0, firm.clients.size, "New firm should have cached 0 clients count"
  35. assert !firm.clients(true).empty?, "New firm should have reloaded client objects"
  36. assert_equal 1, firm.clients(true).size, "New firm should have reloaded clients count"
  37. end
  38. def test_storing_in_pstore
  39. require "tmpdir"
  40. store_filename = File.join(Dir.tmpdir, "ar-pstore-association-test")
  41. File.delete(store_filename) if File.exists?(store_filename)
  42. require "pstore"
  43. apple = Firm.create("name" => "Apple")
  44. natural = Client.new("name" => "Natural Company")
  45. apple.clients << natural
  46. db = PStore.new(store_filename)
  47. db.transaction do
  48. db["apple"] = apple
  49. end
  50. db = PStore.new(store_filename)
  51. db.transaction do
  52. assert_equal "Natural Company", db["apple"].clients.first.name
  53. end
  54. end
  55. end
  56. class AssociationProxyTest < Test::Unit::TestCase
  57. fixtures :authors, :posts, :categorizations, :categories, :developers, :projects, :developers_projects
  58. def test_proxy_accessors
  59. welcome = posts(:welcome)
  60. assert_equal welcome, welcome.author.proxy_owner
  61. assert_equal welcome.class.reflect_on_association(:author), welcome.author.proxy_reflection
  62. welcome.author.class # force load target
  63. assert_equal welcome.author, welcome.author.proxy_target
  64. david = authors(:david)
  65. assert_equal david, david.posts.proxy_owner
  66. assert_equal david.class.reflect_on_association(:posts), david.posts.proxy_reflection
  67. david.posts.first # force load target
  68. assert_equal david.posts, david.posts.proxy_target
  69. assert_equal david, david.posts_with_extension.testing_proxy_owner
  70. assert_equal david.class.reflect_on_association(:posts_with_extension), david.posts_with_extension.testing_proxy_reflection
  71. david.posts_with_extension.first # force load target
  72. assert_equal david.posts_with_extension, david.posts_with_extension.testing_proxy_target
  73. end
  74. def test_push_does_not_load_target
  75. david = authors(:david)
  76. david.categories << categories(:technology)
  77. assert !david.categories.loaded?
  78. assert david.categories.include?(categories(:technology))
  79. end
  80. def test_save_on_parent_does_not_load_target
  81. david = developers(:david)
  82. assert !david.projects.loaded?
  83. david.update_attribute(:created_at, Time.now)
  84. assert !david.projects.loaded?
  85. end
  86. end
  87. class HasOneAssociationsTest < Test::Unit::TestCase
  88. fixtures :accounts, :companies, :developers, :projects, :developers_projects
  89. def setup
  90. Account.destroyed_account_ids.clear
  91. end
  92. def test_has_one
  93. assert_equal companies(:first_firm).account, Account.find(1)
  94. assert_equal Account.find(1).credit_limit, companies(:first_firm).account.credit_limit
  95. end
  96. def test_has_one_cache_nils
  97. firm = companies(:another_firm)
  98. assert_queries(1) { assert_nil firm.account }
  99. assert_queries(0) { assert_nil firm.account }
  100. firms = Firm.find(:all, :include => :account)
  101. assert_queries(0) { firms.each(&:account) }
  102. end
  103. def test_can_marshal_has_one_association_with_nil_target
  104. firm = Firm.new
  105. assert_nothing_raised do
  106. assert_equal firm.attributes, Marshal.load(Marshal.dump(firm)).attributes
  107. end
  108. firm.account
  109. assert_nothing_raised do
  110. assert_equal firm.attributes, Marshal.load(Marshal.dump(firm)).attributes
  111. end
  112. end
  113. def test_proxy_assignment
  114. company = companies(:first_firm)
  115. assert_nothing_raised { company.account = company.account }
  116. end
  117. def test_triple_equality
  118. assert Account === companies(:first_firm).account
  119. assert companies(:first_firm).account === Account
  120. end
  121. def test_type_mismatch
  122. assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).account = 1 }
  123. assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).account = Project.find(1) }
  124. end
  125. def test_natural_assignment
  126. apple = Firm.create("name" => "Apple")
  127. citibank = Account.create("credit_limit" => 10)
  128. apple.account = citibank
  129. assert_equal apple.id, citibank.firm_id
  130. end
  131. def test_natural_assignment_to_nil
  132. old_account_id = companies(:first_firm).account.id
  133. companies(:first_firm).account = nil
  134. companies(:first_firm).save
  135. assert_nil companies(:first_firm).account
  136. # account is dependent, therefore is destroyed when reference to owner is lost
  137. assert_raises(ActiveRecord::RecordNotFound) { Account.find(old_account_id) }
  138. end
  139. def test_assignment_without_replacement
  140. apple = Firm.create("name" => "Apple")
  141. citibank = Account.create("credit_limit" => 10)
  142. apple.account = citibank
  143. assert_equal apple.id, citibank.firm_id
  144. hsbc = apple.build_account({ :credit_limit => 20}, false)
  145. assert_equal apple.id, hsbc.firm_id
  146. hsbc.save
  147. assert_equal apple.id, citibank.firm_id
  148. nykredit = apple.create_account({ :credit_limit => 30}, false)
  149. assert_equal apple.id, nykredit.firm_id
  150. assert_equal apple.id, citibank.firm_id
  151. assert_equal apple.id, hsbc.firm_id
  152. end
  153. def test_assignment_without_replacement_on_create
  154. apple = Firm.create("name" => "Apple")
  155. citibank = Account.create("credit_limit" => 10)
  156. apple.account = citibank
  157. assert_equal apple.id, citibank.firm_id
  158. hsbc = apple.create_account({:credit_limit => 10}, false)
  159. assert_equal apple.id, hsbc.firm_id
  160. hsbc.save
  161. assert_equal apple.id, citibank.firm_id
  162. end
  163. def test_dependence
  164. num_accounts = Account.count
  165. firm = Firm.find(1)
  166. assert !firm.account.nil?
  167. account_id = firm.account.id
  168. assert_equal [], Account.destroyed_account_ids[firm.id]
  169. firm.destroy
  170. assert_equal num_accounts - 1, Account.count
  171. assert_equal [account_id], Account.destroyed_account_ids[firm.id]
  172. end
  173. def test_exclusive_dependence
  174. num_accounts = Account.count
  175. firm = ExclusivelyDependentFirm.find(9)
  176. assert !firm.account.nil?
  177. account_id = firm.account.id
  178. assert_equal [], Account.destroyed_account_ids[firm.id]
  179. firm.destroy
  180. assert_equal num_accounts - 1, Account.count
  181. assert_equal [], Account.destroyed_account_ids[firm.id]
  182. end
  183. def test_dependence_with_nil_associate
  184. firm = DependentFirm.new(:name => 'nullify')
  185. firm.save!
  186. assert_nothing_raised { firm.destroy }
  187. end
  188. def test_succesful_build_association
  189. firm = Firm.new("name" => "GlobalMegaCorp")
  190. firm.save
  191. account = firm.build_account("credit_limit" => 1000)
  192. assert account.save
  193. assert_equal account, firm.account
  194. end
  195. def test_failing_build_association
  196. firm = Firm.new("name" => "GlobalMegaCorp")
  197. firm.save
  198. account = firm.build_account
  199. assert !account.save
  200. assert_equal "can't be empty", account.errors.on("credit_limit")
  201. end
  202. def test_build_association_twice_without_saving_affects_nothing
  203. count_of_account = Account.count
  204. firm = Firm.find(:first)
  205. account1 = firm.build_account("credit_limit" => 1000)
  206. account2 = firm.build_account("credit_limit" => 2000)
  207. assert_equal count_of_account, Account.count
  208. end
  209. def test_create_association
  210. firm = Firm.create(:name => "GlobalMegaCorp")
  211. account = firm.create_account(:credit_limit => 1000)
  212. assert_equal account, firm.reload.account
  213. end
  214. def test_build
  215. firm = Firm.new("name" => "GlobalMegaCorp")
  216. firm.save
  217. firm.account = account = Account.new("credit_limit" => 1000)
  218. assert_equal account, firm.account
  219. assert account.save
  220. assert_equal account, firm.account
  221. end
  222. def test_build_before_child_saved
  223. firm = Firm.find(1)
  224. account = firm.account.build("credit_limit" => 1000)
  225. assert_equal account, firm.account
  226. assert account.new_record?
  227. assert firm.save
  228. assert_equal account, firm.account
  229. assert !account.new_record?
  230. end
  231. def test_build_before_either_saved
  232. firm = Firm.new("name" => "GlobalMegaCorp")
  233. firm.account = account = Account.new("credit_limit" => 1000)
  234. assert_equal account, firm.account
  235. assert account.new_record?
  236. assert firm.save
  237. assert_equal account, firm.account
  238. assert !account.new_record?
  239. end
  240. def test_failing_build_association
  241. firm = Firm.new("name" => "GlobalMegaCorp")
  242. firm.save
  243. firm.account = account = Account.new
  244. assert_equal account, firm.account
  245. assert !account.save
  246. assert_equal account, firm.account
  247. assert_equal "can't be empty", account.errors.on("credit_limit")
  248. end
  249. def test_create
  250. firm = Firm.new("name" => "GlobalMegaCorp")
  251. firm.save
  252. firm.account = account = Account.create("credit_limit" => 1000)
  253. assert_equal account, firm.account
  254. end
  255. def test_create_before_save
  256. firm = Firm.new("name" => "GlobalMegaCorp")
  257. firm.account = account = Account.create("credit_limit" => 1000)
  258. assert_equal account, firm.account
  259. end
  260. def test_dependence_with_missing_association
  261. Account.destroy_all
  262. firm = Firm.find(1)
  263. assert firm.account.nil?
  264. firm.destroy
  265. end
  266. def test_dependence_with_missing_association_and_nullify
  267. Account.destroy_all
  268. firm = DependentFirm.find(:first)
  269. assert firm.account.nil?
  270. firm.destroy
  271. end
  272. def test_assignment_before_parent_saved
  273. firm = Firm.new("name" => "GlobalMegaCorp")
  274. firm.account = a = Account.find(1)
  275. assert firm.new_record?
  276. assert_equal a, firm.account
  277. assert firm.save
  278. assert_equal a, firm.account
  279. assert_equal a, firm.account(true)
  280. end
  281. def test_finding_with_interpolated_condition
  282. firm = Firm.find(:first)
  283. superior = firm.clients.create(:name => 'SuperiorCo')
  284. superior.rating = 10
  285. superior.save
  286. assert_equal 10, firm.clients_with_interpolated_conditions.first.rating
  287. end
  288. def test_assignment_before_child_saved
  289. firm = Firm.find(1)
  290. firm.account = a = Account.new("credit_limit" => 1000)
  291. assert !a.new_record?
  292. assert_equal a, firm.account
  293. assert_equal a, firm.account
  294. assert_equal a, firm.account(true)
  295. end
  296. def test_assignment_before_either_saved
  297. firm = Firm.new("name" => "GlobalMegaCorp")
  298. firm.account = a = Account.new("credit_limit" => 1000)
  299. assert firm.new_record?
  300. assert a.new_record?
  301. assert_equal a, firm.account
  302. assert firm.save
  303. assert !firm.new_record?
  304. assert !a.new_record?
  305. assert_equal a, firm.account
  306. assert_equal a, firm.account(true)
  307. end
  308. def test_not_resaved_when_unchanged
  309. firm = Firm.find(:first, :include => :account)
  310. assert_queries(1) { firm.save! }
  311. firm = Firm.find(:first)
  312. firm.account = Account.find(:first)
  313. assert_queries(1) { firm.save! }
  314. firm = Firm.find(:first).clone
  315. firm.account = Account.find(:first)
  316. assert_queries(2) { firm.save! }
  317. firm = Firm.find(:first).clone
  318. firm.account = Account.find(:first).clone
  319. assert_queries(2) { firm.save! }
  320. end
  321. def test_save_still_works_after_accessing_nil_has_one
  322. jp = Company.new :name => 'Jaded Pixel'
  323. jp.dummy_account.nil?
  324. assert_nothing_raised do
  325. jp.save!
  326. end
  327. end
  328. end
  329. class HasManyAssociationsTest < Test::Unit::TestCase
  330. fixtures :accounts, :companies, :developers, :projects,
  331. :developers_projects, :topics, :authors, :comments
  332. def setup
  333. Client.destroyed_client_ids.clear
  334. end
  335. def force_signal37_to_load_all_clients_of_firm
  336. companies(:first_firm).clients_of_firm.each {|f| }
  337. end
  338. def test_counting_with_counter_sql
  339. assert_equal 2, Firm.find(:first).clients.count
  340. end
  341. def test_counting
  342. assert_equal 2, Firm.find(:first).plain_clients.count
  343. end
  344. def test_counting_with_single_conditions
  345. assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => '1=1')
  346. end
  347. def test_counting_with_single_hash
  348. assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => '1=1')
  349. end
  350. def test_counting_with_column_name_and_hash
  351. assert_equal 2, Firm.find(:first).plain_clients.count(:all, :conditions => '1=1')
  352. end
  353. def test_finding
  354. assert_equal 2, Firm.find(:first).clients.length
  355. end
  356. def test_find_many_with_merged_options
  357. assert_equal 1, companies(:first_firm).limited_clients.size
  358. assert_equal 1, companies(:first_firm).limited_clients.find(:all).size
  359. assert_equal 2, companies(:first_firm).limited_clients.find(:all, :limit => nil).size
  360. end
  361. def test_triple_equality
  362. assert !(Array === Firm.find(:first).clients)
  363. assert Firm.find(:first).clients === Array
  364. end
  365. def test_finding_default_orders
  366. assert_equal "Summit", Firm.find(:first).clients.first.name
  367. end
  368. def test_finding_with_different_class_name_and_order
  369. assert_equal "Microsoft", Firm.find(:first).clients_sorted_desc.first.name
  370. end
  371. def test_finding_with_foreign_key
  372. assert_equal "Microsoft", Firm.find(:first).clients_of_firm.first.name
  373. end
  374. def test_finding_with_condition
  375. assert_equal "Microsoft", Firm.find(:first).clients_like_ms.first.name
  376. end
  377. def test_finding_with_condition_hash
  378. assert_equal "Microsoft", Firm.find(:first).clients_like_ms_with_hash_conditions.first.name
  379. end
  380. def test_finding_using_sql
  381. firm = Firm.find(:first)
  382. first_client = firm.clients_using_sql.first
  383. assert_not_nil first_client
  384. assert_equal "Microsoft", first_client.name
  385. assert_equal 1, firm.clients_using_sql.size
  386. assert_equal 1, Firm.find(:first).clients_using_sql.size
  387. end
  388. def test_counting_using_sql
  389. assert_equal 1, Firm.find(:first).clients_using_counter_sql.size
  390. assert Firm.find(:first).clients_using_counter_sql.any?
  391. assert_equal 0, Firm.find(:first).clients_using_zero_counter_sql.size
  392. assert !Firm.find(:first).clients_using_zero_counter_sql.any?
  393. end
  394. def test_counting_non_existant_items_using_sql
  395. assert_equal 0, Firm.find(:first).no_clients_using_counter_sql.size
  396. end
  397. def test_belongs_to_sanity
  398. c = Client.new
  399. assert_nil c.firm
  400. if c.firm
  401. assert false, "belongs_to failed if check"
  402. end
  403. unless c.firm
  404. else
  405. assert false, "belongs_to failed unless check"
  406. end
  407. end
  408. def test_find_ids
  409. firm = Firm.find(:first)
  410. assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find }
  411. client = firm.clients.find(2)
  412. assert_kind_of Client, client
  413. client_ary = firm.clients.find([2])
  414. assert_kind_of Array, client_ary
  415. assert_equal client, client_ary.first
  416. client_ary = firm.clients.find(2, 3)
  417. assert_kind_of Array, client_ary
  418. assert_equal 2, client_ary.size
  419. assert_equal client, client_ary.first
  420. assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) }
  421. end
  422. def test_find_all
  423. firm = Firm.find(:first)
  424. assert_equal 2, firm.clients.find(:all, :conditions => "#{QUOTED_TYPE} = 'Client'").length
  425. assert_equal 1, firm.clients.find(:all, :conditions => "name = 'Summit'").length
  426. end
  427. def test_find_all_sanitized
  428. firm = Firm.find(:first)
  429. summit = firm.clients.find(:all, :conditions => "name = 'Summit'")
  430. assert_equal summit, firm.clients.find(:all, :conditions => ["name = ?", "Summit"])
  431. assert_equal summit, firm.clients.find(:all, :conditions => ["name = :name", { :name => "Summit" }])
  432. end
  433. def test_find_first
  434. firm = Firm.find(:first)
  435. client2 = Client.find(2)
  436. assert_equal firm.clients.first, firm.clients.find(:first)
  437. assert_equal client2, firm.clients.find(:first, :conditions => "#{QUOTED_TYPE} = 'Client'")
  438. end
  439. def test_find_first_sanitized
  440. firm = Firm.find(:first)
  441. client2 = Client.find(2)
  442. assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = ?", 'Client'])
  443. assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }])
  444. end
  445. def test_find_in_collection
  446. assert_equal Client.find(2).name, companies(:first_firm).clients.find(2).name
  447. assert_raises(ActiveRecord::RecordNotFound) { companies(:first_firm).clients.find(6) }
  448. end
  449. def test_find_grouped
  450. all_clients_of_firm1 = Client.find(:all, :conditions => "firm_id = 1")
  451. grouped_clients_of_firm1 = Client.find(:all, :conditions => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count')
  452. assert_equal 2, all_clients_of_firm1.size
  453. assert_equal 1, grouped_clients_of_firm1.size
  454. end
  455. def test_adding
  456. force_signal37_to_load_all_clients_of_firm
  457. natural = Client.new("name" => "Natural Company")
  458. companies(:first_firm).clients_of_firm << natural
  459. assert_equal 2, companies(:first_firm).clients_of_firm.size # checking via the collection
  460. assert_equal 2, companies(:first_firm).clients_of_firm(true).size # checking using the db
  461. assert_equal natural, companies(:first_firm).clients_of_firm.last
  462. end
  463. def test_adding_using_create
  464. first_firm = companies(:first_firm)
  465. assert_equal 2, first_firm.plain_clients.size
  466. natural = first_firm.plain_clients.create(:name => "Natural Company")
  467. assert_equal 3, first_firm.plain_clients.length
  468. assert_equal 3, first_firm.plain_clients.size
  469. end
  470. def test_adding_a_mismatch_class
  471. assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
  472. assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
  473. assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) }
  474. end
  475. def test_adding_a_collection
  476. force_signal37_to_load_all_clients_of_firm
  477. companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
  478. assert_equal 3, companies(:first_firm).clients_of_firm.size
  479. assert_equal 3, companies(:first_firm).clients_of_firm(true).size
  480. end
  481. def test_adding_before_save
  482. no_of_firms = Firm.count
  483. no_of_clients = Client.count
  484. new_firm = Firm.new("name" => "A New Firm, Inc")
  485. c = Client.new("name" => "Apple")
  486. new_firm.clients_of_firm.push Client.new("name" => "Natural Company")
  487. assert_equal 1, new_firm.clients_of_firm.size
  488. new_firm.clients_of_firm << c
  489. assert_equal 2, new_firm.clients_of_firm.size
  490. assert_equal no_of_firms, Firm.count # Firm was not saved to database.
  491. assert_equal no_of_clients, Client.count # Clients were not saved to database.
  492. assert new_firm.save
  493. assert !new_firm.new_record?
  494. assert !c.new_record?
  495. assert_equal new_firm, c.firm
  496. assert_equal no_of_firms+1, Firm.count # Firm was saved to database.
  497. assert_equal no_of_clients+2, Client.count # Clients were saved to database.
  498. assert_equal 2, new_firm.clients_of_firm.size
  499. assert_equal 2, new_firm.clients_of_firm(true).size
  500. end
  501. def test_invalid_adding
  502. firm = Firm.find(1)
  503. assert !(firm.clients_of_firm << c = Client.new)
  504. assert c.new_record?
  505. assert !firm.valid?
  506. assert !firm.save
  507. assert c.new_record?
  508. end
  509. def test_invalid_adding_before_save
  510. no_of_firms = Firm.count
  511. no_of_clients = Client.count
  512. new_firm = Firm.new("name" => "A New Firm, Inc")
  513. new_firm.clients_of_firm.concat([c = Client.new, Client.new("name" => "Apple")])
  514. assert c.new_record?
  515. assert !c.valid?
  516. assert !new_firm.valid?
  517. assert !new_firm.save
  518. assert c.new_record?
  519. assert new_firm.new_record?
  520. end
  521. def test_build
  522. new_client = companies(:first_firm).clients_of_firm.build("name" => "Another Client")
  523. assert_equal "Another Client", new_client.name
  524. assert new_client.new_record?
  525. assert_equal new_client, companies(:first_firm).clients_of_firm.last
  526. assert companies(:first_firm).save
  527. assert !new_client.new_record?
  528. assert_equal 2, companies(:first_firm).clients_of_firm(true).size
  529. end
  530. def test_build_many
  531. new_clients = companies(:first_firm).clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}])
  532. assert_equal 2, new_clients.size
  533. assert companies(:first_firm).save
  534. assert_equal 3, companies(:first_firm).clients_of_firm(true).size
  535. end
  536. def test_build_without_loading_association
  537. first_topic = topics(:first)
  538. Reply.column_names
  539. assert_equal 1, first_topic.replies.length
  540. assert_no_queries do
  541. first_topic.replies.build(:title => "Not saved", :content => "Superstars")
  542. assert_equal 2, first_topic.replies.size
  543. end
  544. assert_equal 2, first_topic.replies.to_ary.size
  545. end
  546. def test_create_without_loading_association
  547. first_firm = companies(:first_firm)
  548. Firm.column_names
  549. Client.column_names
  550. assert_equal 1, first_firm.clients_of_firm.size
  551. first_firm.clients_of_firm.reset
  552. assert_queries(1) do
  553. first_firm.clients_of_firm.create(:name => "Superstars")
  554. end
  555. assert_equal 2, first_firm.clients_of_firm.size
  556. end
  557. def test_invalid_build
  558. new_client = companies(:first_firm).clients_of_firm.build
  559. assert new_client.new_record?
  560. assert !new_client.valid?
  561. assert_equal new_client, companies(:first_firm).clients_of_firm.last
  562. assert !companies(:first_firm).save
  563. assert new_client.new_record?
  564. assert_equal 1, companies(:first_firm).clients_of_firm(true).size
  565. end
  566. def test_create
  567. force_signal37_to_load_all_clients_of_firm
  568. new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
  569. assert !new_client.new_record?
  570. assert_equal new_client, companies(:first_firm).clients_of_firm.last
  571. assert_equal new_client, companies(:first_firm).clients_of_firm(true).last
  572. end
  573. def test_create_many
  574. companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
  575. assert_equal 3, companies(:first_firm).clients_of_firm(true).size
  576. end
  577. def test_find_or_initialize
  578. the_client = companies(:first_firm).clients.find_or_initialize_by_name("Yet another client")
  579. assert_equal companies(:first_firm).id, the_client.firm_id
  580. assert_equal "Yet another client", the_client.name
  581. assert the_client.new_record?
  582. end
  583. def test_find_or_create
  584. number_of_clients = companies(:first_firm).clients.size
  585. the_client = companies(:first_firm).clients.find_or_create_by_name("Yet another client")
  586. assert_equal number_of_clients + 1, companies(:first_firm, :reload).clients.size
  587. assert_equal the_client, companies(:first_firm).clients.find_or_create_by_name("Yet another client")
  588. assert_equal number_of_clients + 1, companies(:first_firm, :reload).clients.size
  589. end
  590. def test_deleting
  591. force_signal37_to_load_all_clients_of_firm
  592. companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first)
  593. assert_equal 0, companies(:first_firm).clients_of_firm.size
  594. assert_equal 0, companies(:first_firm).clients_of_firm(true).size
  595. end
  596. def test_deleting_before_save
  597. new_firm = Firm.new("name" => "A New Firm, Inc.")
  598. new_client = new_firm.clients_of_firm.build("name" => "Another Client")
  599. assert_equal 1, new_firm.clients_of_firm.size
  600. new_firm.clients_of_firm.delete(new_client)
  601. assert_equal 0, new_firm.clients_of_firm.size
  602. end
  603. def test_deleting_a_collection
  604. force_signal37_to_load_all_clients_of_firm
  605. companies(:first_firm).clients_of_firm.create("name" => "Another Client")
  606. assert_equal 2, companies(:first_firm).clients_of_firm.size
  607. companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]])
  608. assert_equal 0, companies(:first_firm).clients_of_firm.size
  609. assert_equal 0, companies(:first_firm).clients_of_firm(true).size
  610. end
  611. def test_delete_all
  612. force_signal37_to_load_all_clients_of_firm
  613. companies(:first_firm).clients_of_firm.create("name" => "Another Client")
  614. assert_equal 2, companies(:first_firm).clients_of_firm.size
  615. companies(:first_firm).clients_of_firm.delete_all
  616. assert_equal 0, companies(:first_firm).clients_of_firm.size
  617. assert_equal 0, companies(:first_firm).clients_of_firm(true).size
  618. end
  619. def test_delete_all_with_not_yet_loaded_association_collection
  620. force_signal37_to_load_all_clients_of_firm
  621. companies(:first_firm).clients_of_firm.create("name" => "Another Client")
  622. assert_equal 2, companies(:first_firm).clients_of_firm.size
  623. companies(:first_firm).clients_of_firm.reset
  624. companies(:first_firm).clients_of_firm.delete_all
  625. assert_equal 0, companies(:first_firm).clients_of_firm.size
  626. assert_equal 0, companies(:first_firm).clients_of_firm(true).size
  627. end
  628. def test_clearing_an_association_collection
  629. firm = companies(:first_firm)
  630. client_id = firm.clients_of_firm.first.id
  631. assert_equal 1, firm.clients_of_firm.size
  632. firm.clients_of_firm.clear
  633. assert_equal 0, firm.clients_of_firm.size
  634. assert_equal 0, firm.clients_of_firm(true).size
  635. assert_equal [], Client.destroyed_client_ids[firm.id]
  636. # Should not be destroyed since the association is not dependent.
  637. assert_nothing_raised do
  638. assert Client.find(client_id).firm.nil?
  639. end
  640. end
  641. def test_clearing_a_dependent_association_collection
  642. firm = companies(:first_firm)
  643. client_id = firm.dependent_clients_of_firm.first.id
  644. assert_equal 1, firm.dependent_clients_of_firm.size
  645. # :dependent means destroy is called on each client
  646. firm.dependent_clients_of_firm.clear
  647. assert_equal 0, firm.dependent_clients_of_firm.size
  648. assert_equal 0, firm.dependent_clients_of_firm(true).size
  649. assert_equal [client_id], Client.destroyed_client_ids[firm.id]
  650. # Should be destroyed since the association is dependent.
  651. assert Client.find_by_id(client_id).nil?
  652. end
  653. def test_clearing_an_exclusively_dependent_association_collection
  654. firm = companies(:first_firm)
  655. client_id = firm.exclusively_dependent_clients_of_firm.first.id
  656. assert_equal 1, firm.exclusively_dependent_clients_of_firm.size
  657. assert_equal [], Client.destroyed_client_ids[firm.id]
  658. # :exclusively_dependent means each client is deleted directly from
  659. # the database without looping through them calling destroy.
  660. firm.exclusively_dependent_clients_of_firm.clear
  661. assert_equal 0, firm.exclusively_dependent_clients_of_firm.size
  662. assert_equal 0, firm.exclusively_dependent_clients_of_firm(true).size
  663. assert_equal [3], Client.destroyed_client_ids[firm.id]
  664. # Should be destroyed since the association is exclusively dependent.
  665. assert Client.find_by_id(client_id).nil?
  666. end
  667. def test_dependent_association_respects_optional_conditions_on_delete
  668. firm = companies(:odegy)
  669. Client.create(:client_of => firm.id, :name => "BigShot Inc.")
  670. Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
  671. # only one of two clients is included in the association due to the :conditions key
  672. assert_equal 2, Client.find_all_by_client_of(firm.id).size
  673. assert_equal 1, firm.dependent_conditional_clients_of_firm.size
  674. firm.destroy
  675. # only the correctly associated client should have been deleted
  676. assert_equal 1, Client.find_all_by_client_of(firm.id).size
  677. end
  678. def test_dependent_association_respects_optional_sanitized_conditions_on_delete
  679. firm = companies(:odegy)
  680. Client.create(:client_of => firm.id, :name => "BigShot Inc.")
  681. Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
  682. # only one of two clients is included in the association due to the :conditions key
  683. assert_equal 2, Client.find_all_by_client_of(firm.id).size
  684. assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
  685. firm.destroy
  686. # only the correctly associated client should have been deleted
  687. assert_equal 1, Client.find_all_by_client_of(firm.id).size
  688. end
  689. def test_clearing_without_initial_access
  690. firm = companies(:first_firm)
  691. firm.clients_of_firm.clear
  692. assert_equal 0, firm.clients_of_firm.size
  693. assert_equal 0, firm.clients_of_firm(true).size
  694. end
  695. def test_deleting_a_item_which_is_not_in_the_collection
  696. force_signal37_to_load_all_clients_of_firm
  697. summit = Client.find_by_name('Summit')
  698. companies(:first_firm).clients_of_firm.delete(summit)
  699. assert_equal 1, companies(:first_firm).clients_of_firm.size
  700. assert_equal 1, companies(:first_firm).clients_of_firm(true).size
  701. assert_equal 2, summit.client_of
  702. end
  703. def test_deleting_type_mismatch
  704. david = Developer.find(1)
  705. david.projects.reload
  706. assert_raises(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(1) }
  707. end
  708. def test_deleting_self_type_mismatch
  709. david = Developer.find(1)
  710. david.projects.reload
  711. assert_raises(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) }
  712. end
  713. def test_destroy_all
  714. force_signal37_to_load_all_clients_of_firm
  715. assert !companies(:first_firm).clients_of_firm.empty?, "37signals has clients after load"
  716. companies(:first_firm).clients_of_firm.destroy_all
  717. assert companies(:first_firm).clients_of_firm.empty?, "37signals has no clients after destroy all"
  718. assert companies(:first_firm).clients_of_firm(true).empty?, "37signals has no clients after destroy all and refresh"
  719. end
  720. def test_dependence
  721. firm = companies(:first_firm)
  722. assert_equal 2, firm.clients.size
  723. firm.destroy
  724. assert Client.find(:all, :conditions => "firm_id=#{firm.id}").empty?
  725. end
  726. def test_destroy_dependent_when_deleted_from_association
  727. firm = Firm.find(:first)
  728. assert_equal 2, firm.clients.size
  729. client = firm.clients.first
  730. firm.clients.delete(client)
  731. assert_raise(ActiveRecord::RecordNotFound) { Client.find(client.id) }
  732. assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(client.id) }
  733. assert_equal 1, firm.clients.size
  734. end
  735. def test_three_levels_of_dependence
  736. topic = Topic.create "title" => "neat and simple"
  737. reply = topic.replies.create "title" => "neat and simple", "content" => "still digging it"
  738. silly_reply = reply.replies.create "title" => "neat and simple", "content" => "ain't complaining"
  739. assert_nothing_raised { topic.destroy }
  740. end
  741. uses_transaction :test_dependence_with_transaction_support_on_failure
  742. def test_dependence_with_transaction_support_on_failure
  743. firm = companies(:first_firm)
  744. clients = firm.clients
  745. assert_equal 2, clients.length
  746. clients.last.instance_eval { def before_destroy() raise "Trigger rollback" end }
  747. firm.destroy rescue "do nothing"
  748. assert_equal 2, Client.find(:all, :conditions => "firm_id=#{firm.id}").size
  749. end
  750. def test_dependence_on_account
  751. num_accounts = Account.count
  752. companies(:first_firm).destroy
  753. assert_equal num_accounts - 1, Account.count
  754. end
  755. def test_depends_and_nullify
  756. num_accounts = Account.count
  757. num_companies = Company.count
  758. core = companies(:rails_core)
  759. assert_equal accounts(:rails_core_account), core.account
  760. assert_equal companies(:leetsoft, :jadedpixel), core.companies
  761. core.destroy
  762. assert_nil accounts(:rails_core_account).reload.firm_id
  763. assert_nil companies(:leetsoft).reload.client_of
  764. assert_nil companies(:jadedpixel).reload.client_of
  765. assert_equal num_accounts, Account.count
  766. end
  767. def test_included_in_collection
  768. assert companies(:first_firm).clients.include?(Client.find(2))
  769. end
  770. def test_adding_array_and_collection
  771. assert_nothing_raised { Firm.find(:first).clients + Firm.find(:all).last.clients }
  772. end
  773. def test_find_all_without_conditions
  774. firm = companies(:first_firm)
  775. assert_equal 2, firm.clients.find(:all).length
  776. end
  777. def test_replace_with_less
  778. firm = Firm.find(:first)
  779. firm.clients = [companies(:first_client)]
  780. assert firm.save, "Could not save firm"
  781. firm.reload
  782. assert_equal 1, firm.clients.length
  783. end
  784. def test_replace_with_less_and_dependent_nullify
  785. num_companies = Company.count
  786. companies(:rails_core).companies = []
  787. assert_equal num_companies, Company.count
  788. end
  789. def test_replace_with_new
  790. firm = Firm.find(:first)
  791. firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
  792. firm.save
  793. firm.reload
  794. assert_equal 2, firm.clients.length
  795. assert !firm.clients.include?(:first_client)
  796. end
  797. def test_replace_on_new_object
  798. firm = Firm.new("name" => "New Firm")
  799. firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
  800. assert firm.save
  801. firm.reload
  802. assert_equal 2, firm.clients.length
  803. assert firm.clients.include?(Client.find_by_name("New Client"))
  804. end
  805. def test_get_ids
  806. assert_equal [companies(:first_client).id, companies(:second_client).id], companies(:first_firm).client_ids
  807. end
  808. def test_assign_ids
  809. firm = Firm.new("name" => "Apple")
  810. firm.client_ids = [companies(:first_client).id, companies(:second_client).id]
  811. firm.save
  812. firm.reload
  813. assert_equal 2, firm.clients.length
  814. assert firm.clients.include?(companies(:second_client))
  815. end
  816. def test_assign_ids_ignoring_blanks
  817. firm = Firm.create!(:name => 'Apple')
  818. firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
  819. firm.save!
  820. assert_equal 2, firm.clients(true).size
  821. assert firm.clients.include?(companies(:second_client))
  822. end
  823. def test_get_ids_for_through
  824. assert_equal [comments(:eager_other_comment1).id], authors(:mary).comment_ids
  825. end
  826. def test_assign_ids_for_through
  827. assert_raise(NoMethodError) { authors(:mary).comment_ids = [123] }
  828. end
  829. end
  830. class BelongsToAssociationsTest < Test::Unit::TestCase
  831. fixtures :accounts, :companies, :developers, :projects, :topics,
  832. :developers_projects, :computers, :authors, :posts, :tags, :taggings
  833. def test_belongs_to
  834. Client.find(3).firm.name
  835. assert_equal companies(:first_firm).name, Client.find(3).firm.name
  836. assert !Client.find(3).firm.nil?, "Microsoft should have a firm"
  837. end
  838. def test_proxy_assignment
  839. account = Account.find(1)
  840. assert_nothing_raised { account.firm = account.firm }
  841. end
  842. def test_triple_equality
  843. assert Client.find(3).firm === Firm
  844. assert Firm === Client.find(3).firm
  845. end
  846. def test_type_mismatch
  847. assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = 1 }
  848. assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = Project.find(1) }
  849. end
  850. def test_natural_assignment
  851. apple = Firm.create("name" => "Apple")
  852. citibank = Account.create("credit_limit" => 10)
  853. citibank.firm = apple
  854. assert_equal apple.id, citibank.firm_id
  855. end
  856. def test_no_unexpected_aliasing
  857. first_firm = companies(:first_firm)
  858. another_firm = companies(:another_firm)
  859. citibank = Account.create("credit_limit" => 10)
  860. citibank.firm = first_firm
  861. original_proxy = citibank.firm
  862. citibank.firm = another_firm
  863. assert_equal first_firm.object_id, original_proxy.object_id
  864. assert_equal another_firm.object_id, citibank.firm.object_id
  865. end
  866. def test_creating_the_belonging_object
  867. citibank = Account.create("credit_limit" => 10)
  868. apple = citibank.create_firm("name" => "Apple")
  869. assert_equal apple, citibank.firm
  870. citibank.save
  871. citibank.reload
  872. assert_equal apple, citibank.firm
  873. end
  874. def test_building_the_belonging_object
  875. citibank = Account.create("credit_limit" => 10)
  876. apple = citibank.build_firm("name" => "Apple")
  877. citibank.save
  878. assert_equal apple.id, citibank.firm_id
  879. end
  880. def test_natural_assignment_to_nil
  881. client = Client.find(3)
  882. client.firm = nil
  883. client.save
  884. assert_nil client.firm(true)
  885. assert_nil client.client_of
  886. end
  887. def test_with_different_class_name
  888. assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
  889. assert_not_nil Company.find(3).firm_with_other_name, "Microsoft should have a firm"
  890. end
  891. def test_with_condition
  892. assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name
  893. assert_not_nil Company.find(3).firm_with_condition, "Microsoft should have a firm"
  894. end
  895. def test_belongs_to_counter
  896. debate = Topic.create("title" => "debate")
  897. assert_equal 0, debate.send(:read_attribute, "replies_count"), "No replies yet"
  898. trash = debate.replies.create("title" => "blah!", "content" => "world around!")
  899. assert_equal 1, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply created"
  900. trash.destroy
  901. assert_equal 0, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply deleted"
  902. end
  903. def test_belongs_to_counter_with_reassigning
  904. t1 = Topic.create("title" => "t1")
  905. t2 = Topic.create("title" => "t2")
  906. r1 = Reply.new("title" => "r1", "content" => "r1")
  907. r1.topic = t1
  908. assert r1.save
  909. assert_equal 1, Topic.find(t1.id).replies.size
  910. assert_equal 0, Topic.find(t2.id).replies.size
  911. r1.topic = Topic.find(t2.id)
  912. assert r1.save
  913. assert_equal 0, Topic.find(t1.id).replies.size
  914. assert_equal 1, Topic.find(t2.id).replies.size
  915. r1.topic = nil
  916. assert_equal 0, Topic.find(t1.id).replies.size
  917. assert_equal 0, Topic.find(t2.id).replies.size
  918. r1.topic = t1
  919. assert_equal 1, Topic.find(t1.id).replies.size
  920. assert_equal 0, Topic.find(t2.id).replies.size
  921. r1.destroy
  922. assert_equal 0, Topic.find(t1.id).replies.size
  923. assert_equal 0, Topic.find(t2.id).replies.size
  924. end
  925. def test_assignment_before_parent_saved
  926. client = Client.find(:first)
  927. apple = Firm.new("name" => "Apple")
  928. client.firm = apple
  929. assert_equal apple, client.firm
  930. assert apple.new_record?
  931. assert client.save
  932. assert apple.save
  933. assert !apple.new_record?
  934. assert_equal apple, client.firm
  935. assert_equal apple, client.firm(true)
  936. end
  937. def test_assignment_before_child_saved
  938. final_cut = Client.new("name" => "Final Cut")
  939. firm = Firm.find(1)
  940. final_cut.firm = firm
  941. assert final_cut.new_record?
  942. assert final_cut.save
  943. assert !final_cut.new_record?
  944. assert !firm.new_record?
  945. assert_equal firm, final_cut.firm
  946. assert_equal firm, final_cut.firm(true)
  947. end
  948. def test_assignment_before_either_saved
  949. final_cut = Client.new("name" => "Final Cut")
  950. apple = Firm.new("name" => "Apple")
  951. final_cut.firm = apple
  952. assert final_cut.new_record?
  953. assert apple.new_record?
  954. assert final_cut.save
  955. assert !final_cut.new_record?
  956. assert !apple.new_record?
  957. assert_equal apple, final_cut.firm
  958. assert_equal apple, final_cut.firm(true)
  959. end
  960. def test_new_record_with_foreign_key_but_no_object
  961. c = Client.new("firm_id" => 1)
  962. assert_equal Firm.find(:first), c.firm_with_basic_id
  963. end
  964. def test_forgetting_the_load_when_foreign_key_enters_late
  965. c = Client.new
  966. assert_nil c.firm_with_basic_id
  967. c.firm_id = 1
  968. assert_equal Firm.find(:first), c.firm_with_basic_id
  969. end
  970. def test_field_name_same_as_foreign_key
  971. computer = Computer.find(1)
  972. assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # '
  973. end
  974. def test_counter_cache
  975. topic = Topic.create :title => "Zoom-zoom-zoom"
  976. assert_equal 0, topic[:replies_count]
  977. reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
  978. reply.topic = topic
  979. assert_equal 1, topic.reload[:replies_count]
  980. assert_equal 1, topic.replies.size
  981. topic[:replies_count] = 15
  982. assert_equal 15, topic.replies.size
  983. end
  984. def test_custom_counter_cache
  985. reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
  986. assert_equal 0, reply[:replies_count]
  987. silly = SillyReply.create(:title => "gaga", :content => "boo-boo")
  988. silly.reply = reply
  989. assert_equal 1, reply.reload[:replies_count]
  990. assert_equal 1, reply.replies.size
  991. reply[:replies_count] = 17
  992. assert_equal 17, reply.replies.size
  993. end
  994. def test_store_two_association_with_one_save
  995. num_orders = Order.count
  996. num_customers = Customer.count
  997. order = Order.new
  998. customer1 = order.billing = Customer.new
  999. customer2 = order.shipping = Customer.new
  1000. assert order.save
  1001. assert_equal customer1, order.billing
  1002. assert_equal customer2, order.shipping
  1003. order.reload
  1004. assert_equal customer1, order.billing
  1005. assert_equal customer2, order.shipping
  1006. assert_equal num_orders +1, Order.count
  1007. assert_equal num_customers +2, Customer.count
  1008. end
  1009. def test_store_association_in_two_relations_with_one_save
  1010. num_orders = Order.count
  1011. num_customers = Customer.count
  1012. order = Order.new
  1013. customer = order.billing = order.shipping = Customer.new
  1014. assert order.save
  1015. assert_equal customer, order.billing
  1016. assert_equal customer, order.shipping
  1017. order.reload
  1018. assert_equal customer, order.billing
  1019. assert_equal customer, order.shipping
  1020. assert_equal num_orders +1, Order.count
  1021. assert_equal num_customers +1, Customer.count
  1022. end
  1023. def test_store_association_in_two_relations_with_one_save_in_existing_object
  1024. num_orders = Order.count
  1025. num_customers = Customer.count
  1026. order = Order.create
  1027. customer = order.billing = order.shipping = Customer.new
  1028. assert order.save
  1029. assert_equal customer, order.billing
  1030. assert_equal customer, order.shipping
  1031. order.reload
  1032. assert_equal customer, order.billing
  1033. assert_equal customer, order.shipping
  1034. assert_equal num_orders +1, Order.count
  1035. assert_equal num_customers +1, Customer.count
  1036. end
  1037. def test_store_association_in_two_relations_with_one_save_in_existing_object_with_values
  1038. num_orders = Order.count
  1039. num_customers = Customer.count
  1040. order = Order.create
  1041. customer = order.billing = order.shipping = Customer.new
  1042. assert order.save
  1043. assert_equal customer, order.billing
  1044. assert_equal customer, order.shipping
  1045. order.reload
  1046. customer = order.billing = order.shipping = Customer.new
  1047. assert order.save
  1048. order.reload
  1049. assert_equal customer, order.billing
  1050. assert_equal customer, order.shipping
  1051. assert_equal num_orders +1, Order.count
  1052. assert_equal num_customers +2, Customer.count
  1053. end
  1054. def test_association_assignment_sticks
  1055. post = Post.find(:first)
  1056. author1, author2 = Author.find(:all, :limit => 2)
  1057. assert_not_nil author1
  1058. assert_not_nil author2
  1059. # make sure the association is loaded
  1060. post.author
  1061. # set the association by id, directly
  1062. post.author_id = author2.id
  1063. # save and reload
  1064. post.save!
  1065. post.reload
  1066. # the author id of the post should be the id we set
  1067. assert_equal post.author_id, author2.id
  1068. end
  1069. end
  1070. class ProjectWithAfterCreateHook < ActiveRecord::Base
  1071. set_table_name 'projects'
  1072. has_and_belongs_to_many :developers,
  1073. :class_name => "DeveloperForProjectWithAfterCreateHook",
  1074. :join_table => "developers_projects",
  1075. :foreign_key => "project_id",
  1076. :association_foreign_key => "developer_id"
  1077. after_create :add_david
  1078. def add_david
  1079. david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
  1080. david.projects << self
  1081. end
  1082. end
  1083. class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
  1084. set_table_name 'developers'
  1085. has_and_belongs_to_many :projects,
  1086. :class_name => "ProjectWithAfterCreateHook",
  1087. :join_table => "developers_projects",
  1088. :association_foreign_key => "project_id",
  1089. :foreign_key => "developer_id"
  1090. end
  1091. class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
  1092. fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects
  1093. def test_has_and_belongs_to_many
  1094. david = Developer.find(1)
  1095. assert !david.projects.empty?
  1096. assert_equal 2, david.projects.size
  1097. active_record = Project.find(1)
  1098. assert !active_record.developers.empty?
  1099. assert_equal 3, active_record.developers.size
  1100. assert active_record.developers.include?(david)
  1101. end
  1102. def test_triple_equality
  1103. assert !(Array === Developer.find(1).projects)
  1104. assert Developer.find(1).projects === Array
  1105. end
  1106. def test_adding_single
  1107. jamis = Developer.find(2)
  1108. jamis.projects.reload # causing the collection to load
  1109. action_controller = Project.find(2)
  1110. assert_equal 1, jamis.projects.size
  1111. assert_equal 1, action_controller.developers.size
  1112. jamis.projects << action_controller
  1113. assert_equal 2, jamis.projects.size
  1114. assert_equal 2, jamis.projects(true).size
  1115. assert_equal 2, action_controller.developers(true).size
  1116. end
  1117. def test_adding_type_mismatch
  1118. jamis = Developer.find(2)
  1119. assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << nil }
  1120. assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << 1 }
  1121. end
  1122. def test_adding_from_the_project
  1123. jamis = Developer.find(2)
  1124. action_controller = Project.find(2)
  1125. action_controller.developers.reload
  1126. assert_equal 1, jamis.projects.size
  1127. assert_equal 1, action_controller.developers.size
  1128. action_controller.developers << jamis
  1129. assert_equal 2, jamis.projects(true).size
  1130. assert_equal 2, action_controller.developers.size
  1131. assert_equal 2, action_controller.developers(true).size
  1132. end
  1133. def test_adding_from_the_project_fixed_timestamp
  1134. jamis = Developer.find(2)
  1135. action_controller = Project.find(2)
  1136. action_controller.developers.reload
  1137. assert_equal 1, jamis.projects.size
  1138. assert_equal 1, action_controller.developers.size
  1139. updated_at = jamis.updated_at
  1140. action_controller.developers << jamis
  1141. assert_equal updated_at, jamis.updated_at
  1142. assert_equal 2, jamis.projects(true).size
  1143. assert_equal 2, action_controller.developers.size
  1144. assert_equal 2, action_controller.developers(true).size
  1145. end
  1146. def test_adding_multiple
  1147. aredridel = Developer.new("name" => "Aredridel")
  1148. aredridel.save
  1149. aredridel.projects.reload
  1150. aredridel.projects.push(Project.find(1), Project.find(2))
  1151. assert_equal 2, aredridel.projects.size
  1152. assert_equal 2, aredridel.projects(true).size
  1153. end
  1154. def test_adding_a_collection
  1155. aredridel = Developer.new("name" => "Aredridel")
  1156. aredridel.save
  1157. aredridel.projects.reload
  1158. aredridel.projects.concat([Project.find(1), Project.find(2)])
  1159. assert_equal 2, aredridel.projects.size
  1160. assert_equal 2, aredridel.projects(true).size
  1161. end
  1162. def test_adding_uses_default_values_on_join_table
  1163. ac = projects(:action_controller)
  1164. assert !developers(:jamis).projects.include?(ac)
  1165. developers(:jamis).projects << ac
  1166. assert developers(:jamis, :reload).projects.include?(ac)
  1167. project = developers(:jamis).projects.detect { |p| p == ac }
  1168. assert_equal 1, project.access_level.to_i
  1169. end
  1170. def test_hatbm_attribute_access_and_respond_to
  1171. project = developers(:jamis).projects[0]
  1172. assert project.has_attribute?("name")
  1173. assert project.has_attribute?("joined_on")
  1174. assert project.has_attribute?("access_level")
  1175. assert project.respond_to?("name")
  1176. assert project.respond_to?("name=")
  1177. assert project.respond_to?("name?")
  1178. assert project.respond_to?("joined_on")
  1179. # given that the 'join attribute' won't be persisted, I don't
  1180. # think we should define the mutators
  1181. #assert project.respond_to?("joined_on=")
  1182. assert project.respond_to?("joined_on?")
  1183. assert project.respond_to?("access_level")
  1184. #assert project.respond_to?("access_level=")
  1185. assert project.respond_to?("access_level?")
  1186. end
  1187. def test_habtm_adding_before_save
  1188. no_of_devels = Developer.count
  1189. no_of_projects = Project.count
  1190. aredridel = Developer.new("name" => "Aredridel")
  1191. aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
  1192. assert aredridel.new_record?
  1193. assert p.new_record?
  1194. assert aredridel.save
  1195. assert !aredridel.new_record?
  1196. assert_equal no_of_devels+1, Developer.count
  1197. assert_equal no_of_projects+1, Project.count
  1198. assert_equal 2, aredridel.projects.size
  1199. assert_equal 2, aredridel.projects(true).size
  1200. end
  1201. def test_habtm_saving_multiple_relationships
  1202. new_project = Project.new("name" => "Grimetime")
  1203. amount_of_developers = 4
  1204. developers = (0...amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") }.reverse
  1205. new_project.developer_ids = [developers[0].id, developers[1].id]
  1206. new_project.developers_with_callback_ids = [developers[2].id, developers[3].id]
  1207. assert new_project.save
  1208. new_project.reload
  1209. assert_equal amount_of_developers, new_project.developers.size
  1210. assert_equal developers, new_project.developers
  1211. end
  1212. def test_habtm_unique_order_preserved
  1213. assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).non_unique_developers
  1214. assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).developers
  1215. end
  1216. def test_build
  1217. devel = Developer.find(1)
  1218. proj = devel.projects.build("name" => "Projekt")
  1219. assert_equal devel.projects.last, proj
  1220. assert proj.new_record?
  1221. devel

Large files files are truncated, but you can click here to view the full file