This project is archived and is in readonly mode.

#516 ✓stale

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

class Head
  belongs_to :chicken
  validates_uniqueness_of :chicken_id

>> @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

    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...



  • Oleg

    Oleg July 1st, 2008 @ 12:45 AM

    create_head is the Rails built-in method. See:

    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

    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

    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 ="chicken_id" => id);; 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

    nikz July 6th, 2008 @ 05:12 AM

    • Tag changed from activerecord to activerecord, edge, patch, tested

    Patch against edge attached :)

  • josh

    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

    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.

  • bingbing

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=""></a>