Merged updates from trunk into stable branch
[feedcatcher.git] / vendor / rails / activerecord / test / cases / associations / belongs_to_associations_test.rb
1 require "cases/helper"
2 require 'models/developer'
3 require 'models/project'
4 require 'models/company'
5 require 'models/topic'
6 require 'models/reply'
7 require 'models/computer'
8 require 'models/customer'
9 require 'models/order'
10 require 'models/post'
11 require 'models/author'
12 require 'models/tag'
13 require 'models/tagging'
14 require 'models/comment'
15 require 'models/sponsor'
16 require 'models/member'
17
18 class BelongsToAssociationsTest < ActiveRecord::TestCase
19 fixtures :accounts, :companies, :developers, :projects, :topics,
20 :developers_projects, :computers, :authors, :posts, :tags, :taggings, :comments
21
22 def test_belongs_to
23 Client.find(3).firm.name
24 assert_equal companies(:first_firm).name, Client.find(3).firm.name
25 assert !Client.find(3).firm.nil?, "Microsoft should have a firm"
26 end
27
28 def test_proxy_assignment
29 account = Account.find(1)
30 assert_nothing_raised { account.firm = account.firm }
31 end
32
33 def test_triple_equality
34 assert Client.find(3).firm === Firm
35 assert Firm === Client.find(3).firm
36 end
37
38 def test_type_mismatch
39 assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = 1 }
40 assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = Project.find(1) }
41 end
42
43 def test_natural_assignment
44 apple = Firm.create("name" => "Apple")
45 citibank = Account.create("credit_limit" => 10)
46 citibank.firm = apple
47 assert_equal apple.id, citibank.firm_id
48 end
49
50 def test_no_unexpected_aliasing
51 first_firm = companies(:first_firm)
52 another_firm = companies(:another_firm)
53
54 citibank = Account.create("credit_limit" => 10)
55 citibank.firm = first_firm
56 original_proxy = citibank.firm
57 citibank.firm = another_firm
58
59 assert_equal first_firm.object_id, original_proxy.target.object_id
60 assert_equal another_firm.object_id, citibank.firm.target.object_id
61 end
62
63 def test_creating_the_belonging_object
64 citibank = Account.create("credit_limit" => 10)
65 apple = citibank.create_firm("name" => "Apple")
66 assert_equal apple, citibank.firm
67 citibank.save
68 citibank.reload
69 assert_equal apple, citibank.firm
70 end
71
72 def test_building_the_belonging_object
73 citibank = Account.create("credit_limit" => 10)
74 apple = citibank.build_firm("name" => "Apple")
75 citibank.save
76 assert_equal apple.id, citibank.firm_id
77 end
78
79 def test_natural_assignment_to_nil
80 client = Client.find(3)
81 client.firm = nil
82 client.save
83 assert_nil client.firm(true)
84 assert_nil client.client_of
85 end
86
87 def test_with_different_class_name
88 assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
89 assert_not_nil Company.find(3).firm_with_other_name, "Microsoft should have a firm"
90 end
91
92 def test_with_condition
93 assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name
94 assert_not_nil Company.find(3).firm_with_condition, "Microsoft should have a firm"
95 end
96
97 def test_with_select
98 assert_equal Company.find(2).firm_with_select.attributes.size, 1
99 assert_equal Company.find(2, :include => :firm_with_select ).firm_with_select.attributes.size, 1
100 end
101
102 def test_belongs_to_counter
103 debate = Topic.create("title" => "debate")
104 assert_equal 0, debate.send(:read_attribute, "replies_count"), "No replies yet"
105
106 trash = debate.replies.create("title" => "blah!", "content" => "world around!")
107 assert_equal 1, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply created"
108
109 trash.destroy
110 assert_equal 0, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply deleted"
111 end
112
113 def test_belongs_to_counter_with_assigning_nil
114 p = Post.find(1)
115 c = Comment.find(1)
116
117 assert_equal p.id, c.post_id
118 assert_equal 2, Post.find(p.id).comments.size
119
120 c.post = nil
121
122 assert_equal 1, Post.find(p.id).comments.size
123 end
124
125 def test_belongs_to_counter_with_reassigning
126 t1 = Topic.create("title" => "t1")
127 t2 = Topic.create("title" => "t2")
128 r1 = Reply.new("title" => "r1", "content" => "r1")
129 r1.topic = t1
130
131 assert r1.save
132 assert_equal 1, Topic.find(t1.id).replies.size
133 assert_equal 0, Topic.find(t2.id).replies.size
134
135 r1.topic = Topic.find(t2.id)
136
137 assert r1.save
138 assert_equal 0, Topic.find(t1.id).replies.size
139 assert_equal 1, Topic.find(t2.id).replies.size
140
141 r1.topic = nil
142
143 assert_equal 0, Topic.find(t1.id).replies.size
144 assert_equal 0, Topic.find(t2.id).replies.size
145
146 r1.topic = t1
147
148 assert_equal 1, Topic.find(t1.id).replies.size
149 assert_equal 0, Topic.find(t2.id).replies.size
150
151 r1.destroy
152
153 assert_equal 0, Topic.find(t1.id).replies.size
154 assert_equal 0, Topic.find(t2.id).replies.size
155 end
156
157 def test_belongs_to_reassign_with_namespaced_models_and_counters
158 t1 = Web::Topic.create("title" => "t1")
159 t2 = Web::Topic.create("title" => "t2")
160 r1 = Web::Reply.new("title" => "r1", "content" => "r1")
161 r1.topic = t1
162
163 assert r1.save
164 assert_equal 1, Web::Topic.find(t1.id).replies.size
165 assert_equal 0, Web::Topic.find(t2.id).replies.size
166
167 r1.topic = Web::Topic.find(t2.id)
168
169 assert r1.save
170 assert_equal 0, Web::Topic.find(t1.id).replies.size
171 assert_equal 1, Web::Topic.find(t2.id).replies.size
172 end
173
174 def test_belongs_to_counter_after_save
175 topic = Topic.create!(:title => "monday night")
176 topic.replies.create!(:title => "re: monday night", :content => "football")
177 assert_equal 1, Topic.find(topic.id)[:replies_count]
178
179 topic.save!
180 assert_equal 1, Topic.find(topic.id)[:replies_count]
181 end
182
183 def test_belongs_to_counter_after_update_attributes
184 topic = Topic.create!(:title => "37s")
185 topic.replies.create!(:title => "re: 37s", :content => "rails")
186 assert_equal 1, Topic.find(topic.id)[:replies_count]
187
188 topic.update_attributes(:title => "37signals")
189 assert_equal 1, Topic.find(topic.id)[:replies_count]
190 end
191
192 def test_belongs_to_counter_after_save
193 topic = Topic.create("title" => "monday night")
194 topic.replies.create("title" => "re: monday night", "content" => "football")
195 assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
196
197 topic.save
198 assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
199 end
200
201 def test_belongs_to_counter_after_update_attributes
202 topic = Topic.create("title" => "37s")
203 topic.replies.create("title" => "re: 37s", "content" => "rails")
204 assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
205
206 topic.update_attributes("title" => "37signals")
207 assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
208 end
209
210 def test_assignment_before_child_saved
211 final_cut = Client.new("name" => "Final Cut")
212 firm = Firm.find(1)
213 final_cut.firm = firm
214 assert final_cut.new_record?
215 assert final_cut.save
216 assert !final_cut.new_record?
217 assert !firm.new_record?
218 assert_equal firm, final_cut.firm
219 assert_equal firm, final_cut.firm(true)
220 end
221
222 def test_new_record_with_foreign_key_but_no_object
223 c = Client.new("firm_id" => 1)
224 assert_equal Firm.find(:first), c.firm_with_basic_id
225 end
226
227 def test_forgetting_the_load_when_foreign_key_enters_late
228 c = Client.new
229 assert_nil c.firm_with_basic_id
230
231 c.firm_id = 1
232 assert_equal Firm.find(:first), c.firm_with_basic_id
233 end
234
235 def test_field_name_same_as_foreign_key
236 computer = Computer.find(1)
237 assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # '
238 end
239
240 def test_counter_cache
241 topic = Topic.create :title => "Zoom-zoom-zoom"
242 assert_equal 0, topic[:replies_count]
243
244 reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
245 reply.topic = topic
246
247 assert_equal 1, topic.reload[:replies_count]
248 assert_equal 1, topic.replies.size
249
250 topic[:replies_count] = 15
251 assert_equal 15, topic.replies.size
252 end
253
254 def test_custom_counter_cache
255 reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
256 assert_equal 0, reply[:replies_count]
257
258 silly = SillyReply.create(:title => "gaga", :content => "boo-boo")
259 silly.reply = reply
260
261 assert_equal 1, reply.reload[:replies_count]
262 assert_equal 1, reply.replies.size
263
264 reply[:replies_count] = 17
265 assert_equal 17, reply.replies.size
266 end
267
268 def test_association_assignment_sticks
269 post = Post.find(:first)
270
271 author1, author2 = Author.find(:all, :limit => 2)
272 assert_not_nil author1
273 assert_not_nil author2
274
275 # make sure the association is loaded
276 post.author
277
278 # set the association by id, directly
279 post.author_id = author2.id
280
281 # save and reload
282 post.save!
283 post.reload
284
285 # the author id of the post should be the id we set
286 assert_equal post.author_id, author2.id
287 end
288
289 def test_cant_save_readonly_association
290 assert_raise(ActiveRecord::ReadOnlyRecord) { companies(:first_client).readonly_firm.save! }
291 assert companies(:first_client).readonly_firm.readonly?
292 end
293
294 def test_polymorphic_assignment_foreign_type_field_updating
295 # should update when assigning a saved record
296 sponsor = Sponsor.new
297 member = Member.create
298 sponsor.sponsorable = member
299 assert_equal "Member", sponsor.sponsorable_type
300
301 # should update when assigning a new record
302 sponsor = Sponsor.new
303 member = Member.new
304 sponsor.sponsorable = member
305 assert_equal "Member", sponsor.sponsorable_type
306 end
307
308 def test_polymorphic_assignment_updates_foreign_id_field_for_new_and_saved_records
309 sponsor = Sponsor.new
310 saved_member = Member.create
311 new_member = Member.new
312
313 sponsor.sponsorable = saved_member
314 assert_equal saved_member.id, sponsor.sponsorable_id
315
316 sponsor.sponsorable = new_member
317 assert_equal nil, sponsor.sponsorable_id
318 end
319
320 def test_belongs_to_proxy_should_not_respond_to_private_methods
321 assert_raise(NoMethodError) { companies(:first_firm).private_method }
322 assert_raise(NoMethodError) { companies(:second_client).firm.private_method }
323 end
324
325 def test_belongs_to_proxy_should_respond_to_private_methods_via_send
326 companies(:first_firm).send(:private_method)
327 companies(:second_client).firm.send(:private_method)
328 end
329
330 def test_save_of_record_with_loaded_belongs_to
331 @account = companies(:first_firm).account
332
333 assert_nothing_raised do
334 Account.find(@account.id).save!
335 Account.find(@account.id, :include => :firm).save!
336 end
337
338 @account.firm.delete
339
340 assert_nothing_raised do
341 Account.find(@account.id).save!
342 Account.find(@account.id, :include => :firm).save!
343 end
344 end
345 end