3 require 'models/person'
4 require 'models/reader'
5 require 'models/comment'
7 class HasManyThroughAssociationsTest
< ActiveRecord
::TestCase
8 fixtures
:posts, :readers, :people, :comments, :authors
10 def test_associate_existing
11 assert_queries(2) { posts(:thinking);people(:david) }
13 posts(:thinking).people
16 posts(:thinking).people
<< people(:david)
20 assert
posts(:thinking).people
.include?(people(:david))
23 assert
posts(:thinking).reload
.people(true).include?(people(:david))
26 def test_associating_new
27 assert_queries(1) { posts(:thinking) }
28 new_person
= nil # so block binding catches it
31 new_person
= Person
.new
:first_name => 'bob'
34 # Associating new records always saves them
35 # Thus, 1 query for the new person record, 1 query for the new join table record
37 posts(:thinking).people
<< new_person
41 assert
posts(:thinking).people
.include?(new_person
)
44 assert
posts(:thinking).reload
.people(true).include?(new_person
)
47 def test_associate_new_by_building
48 assert_queries(1) { posts(:thinking) }
51 posts(:thinking).people
.build(:first_name=>"Bob")
52 posts(:thinking).people
.new(:first_name=>"Ted")
55 # Should only need to load the association once
57 assert
posts(:thinking).people
.collect(&:first_name).include?("Bob")
58 assert
posts(:thinking).people
.collect(&:first_name).include?("Ted")
61 # 2 queries for each new record (1 to save the record itself, 1 for the join model)
63 # + 1 query to save the actual post = 5
65 posts(:thinking).body
+= '-changed'
69 assert
posts(:thinking).reload
.people(true).collect(&:first_name).include?("Bob")
70 assert
posts(:thinking).reload
.people(true).collect(&:first_name).include?("Ted")
73 def test_delete_association
74 assert_queries(2){posts(:welcome);people(:michael); }
77 posts(:welcome).people
.delete(people(:michael))
81 assert
posts(:welcome).people
.empty
?
84 assert
posts(:welcome).reload
.people(true).empty
?
87 def test_replace_association
88 assert_queries(4){posts(:welcome);people(:david);people(:michael); posts(:welcome).people(true)}
90 # 1 query to delete the existing reader (michael)
91 # 1 query to associate the new reader (david)
93 posts(:welcome).people
= [people(:david)]
97 assert
posts(:welcome).people
.include?(people(:david))
98 assert
!posts(:welcome).people
.include?(people(:michael))
101 assert
posts(:welcome).reload
.people(true).include?(people(:david))
102 assert
!posts(:welcome).reload
.people(true).include?(people(:michael))
105 def test_associate_with_create
106 assert_queries(1) { posts(:thinking) }
108 # 1 query for the new record, 1 for the join table record
109 # No need to update the actual collection yet!
111 posts(:thinking).people
.create(:first_name=>"Jeb")
114 # *Now* we actually need the collection so it's loaded
116 assert
posts(:thinking).people
.collect(&:first_name).include?("Jeb")
119 assert
posts(:thinking).reload
.people(true).collect(&:first_name).include?("Jeb")
122 def test_associate_with_create_and_no_options
123 peeps
= posts(:thinking).people
.count
124 posts(:thinking).people
.create(:first_name => 'foo')
125 assert_equal peeps
+ 1, posts(:thinking).people
.count
128 def test_associate_with_create_exclamation_and_no_options
129 peeps
= posts(:thinking).people
.count
130 posts(:thinking).people
.create
!(:first_name => 'foo')
131 assert_equal peeps
+ 1, posts(:thinking).people
.count
134 def test_clear_associations
135 assert_queries(2) { posts(:welcome);posts(:welcome).people(true) }
138 posts(:welcome).people
.clear
142 assert
posts(:welcome).people
.empty
?
145 assert
posts(:welcome).reload
.people(true).empty
?
148 def test_association_callback_ordering
151 post
= posts(:thinking)
153 post
.people_with_callbacks
<< people(:michael)
155 [:added, :before, "Michael"],
156 [:added, :after, "Michael"]
159 post
.people_with_callbacks
.push(people(:david), Person
.create
!(:first_name => "Bob"), Person
.new(:first_name => "Lary"))
161 [:added, :before, "David"],
162 [:added, :after, "David"],
163 [:added, :before, "Bob"],
164 [:added, :after, "Bob"],
165 [:added, :before, "Lary"],
166 [:added, :after, "Lary"]
169 post
.people_with_callbacks
.build(:first_name => "Ted")
171 [:added, :before, "Ted"],
172 [:added, :after, "Ted"]
175 post
.people_with_callbacks
.create(:first_name => "Sam")
177 [:added, :before, "Sam"],
178 [:added, :after, "Sam"]
181 post
.people_with_callbacks
= [people(:michael),people(:david), Person
.new(:first_name => "Julian"), Person
.create
!(:first_name => "Roger")]
182 assert_equal (%w(Ted Bob Sam Lary
) * 2).sort
, log
[-12..-5].collect(&:last).sort
184 [:added, :before, "Julian"],
185 [:added, :after, "Julian"],
186 [:added, :before, "Roger"],
187 [:added, :after, "Roger"]
190 post
.people_with_callbacks
.clear
191 assert_equal (%w(Michael David Julian Roger
) * 2).sort
, log
.last(8).collect(&:last).sort
194 def test_dynamic_find_should_respect_association_include
195 # SQL error in sort clause if :include is not included
196 # due to Unknown column 'comments.id'
197 assert Person
.find(1).posts_with_comments_sorted_by_comment_id
.find_by_title('Welcome to the weblog')
200 def test_count_with_include_should_alias_join_table
201 assert_equal
2, people(:michael).posts
.count(:include => :readers)
205 assert_equal
[posts(:welcome).id
, posts(:authorless).id
].sort
, people(:michael).post_ids
.sort
208 def test_get_ids_for_loaded_associations
209 person
= people(:michael)
217 def test_get_ids_for_unloaded_associations_does_not_load_them
218 person
= people(:michael)
219 assert
!person
.posts
.loaded
?
220 assert_equal
[posts(:welcome).id
, posts(:authorless).id
].sort
, person
.post_ids
.sort
221 assert
!person
.posts
.loaded
?
224 uses_mocha
'mocking Tag.transaction' do
225 def test_association_proxy_transaction_method_starts_transaction_in_association_class
226 Tag
.expects(:transaction)
227 Post
.find(:first).tags
.transaction
do
233 def test_has_many_association_through_a_belongs_to_association_where_the_association_doesnt_exist
234 author
= authors(:mary)
235 post
= Post
.create
!(:title => "TITLE", :body => "BODY")
236 assert_equal
[], post
.author_favorites
239 def test_has_many_association_through_a_belongs_to_association
240 author
= authors(:mary)
241 post
= Post
.create
!(:author => author
, :title => "TITLE", :body => "BODY")
242 author
.author_favorites
.create(:favorite_author_id => 1)
243 author
.author_favorites
.create(:favorite_author_id => 2)
244 author
.author_favorites
.create(:favorite_author_id => 3)
245 assert_equal post
.author
.author_favorites
, post
.author_favorites