This project is archived and is in readonly mode.
has_one + validation Object#create_something bug
Reported by Oleg | June 30th, 2008 @ 08:11 PM | in 2.x
Odd one I found today:
class Chicken
has_one :head
end
class Head
belongs_to :chicken
validates_uniqueness_of :chicken_id
end
>> @chicken = Chicken.first
>> @chicken.create_head
=> #<Head id: 10, chicken_id: 1>
# second create should trigger validation error, or at least do nothing. Instead we get this:
>> @chicken.create_head
=> #<Head id: nil, chicken_id: 1>
For some reason second call to create_head generates SQL similar to this:
SELECT `chicken_id` FROM `heads` WHERE (`heads`.chicken_id = 1)
SELECT `chicken_id` FROM `heads` WHERE (`heads`.chicken_id IS NULL AND `heads`.id <> 10)
UPDATE `heads` SET `chicken_id` = NULL, WHERE `id` = 10
Doesn't make much sense to me
Comments and changes to this ticket
-
nikz June 30th, 2008 @ 11:39 PM
Hey Oleg,
It's not to do with scoping at all is it?
What does your create_head method look like?
I've run into this one previously I think...
Cheers,
Nik
-
Oleg July 1st, 2008 @ 12:45 AM
create_head is the Rails built-in method. See: http://rails-doc.org/docs/Active...
I have a feeling that something gets messed due to the validation method. I might dig a bit deeper later, but for now I just threw this bug here.
In any case create_* method should not generate UPDATE sql. That makes no sense.
It's Rails 2.1 I didn't see a mention of something like that in tickets so I assume edge has the same issue, probably.
-
nikz July 5th, 2008 @ 05:15 AM
Hey Oleg,
Ah right :) Nope, I don't think it's to do with the bug I ran into before upon closer inspection.
I'm still playing with it (as the fact that you get back an unsaved Head is totally a bug).
The UPDATE query is just to preserve the integrity of the has_one - i.e it's de-associating the old Head. But it looks like it's not saving the new Head.
Hope that helps :)
-
nikz July 5th, 2008 @ 05:37 AM
It looks like Rails isn't saving the second head - the query:
SELECT `chicken_id` FROM `heads` WHERE (`heads`.chicken_id IS NULL AND `heads`.id <> 10)
is the validates_uniqueness_of failing :) If you comment that validation out, you'll see that Rails does two INSERTs.
I guess the bug here is that it null-ifys the old Head, even though the new one has failed validation.
The docs say create_whatever should work like;
h = Head.new("chicken_id" => id); h.save; h
And it is - returning an un-saved Head.
So, I'll write up a patch to make sure it only runs HasOneAssociation#replace if the validations pass? Does that make sense to everyone?
-
nikz July 6th, 2008 @ 05:12 AM
- Tag changed from activerecord to activerecord, edge, patch, tested
Patch against edge attached :)
-
josh October 28th, 2008 @ 04:21 PM
- State changed from new to stale
Staling out, please reopen if this is still a problem.
-
Jack Neto January 18th, 2010 @ 07:54 PM
Hey guys,
It's been a while since this bug showed it's ugly face.
I'm using Rails 2.3.5 and I still have the same problem.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>