Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

has_one dependent nullify deletes associated object on change

#1305

Using Rails 2.1.1

class User < ActiveRecord::Base
  has_one :device, :dependent => :nullify
end
u = User.find(1)
u.device = Device.find(1)
u.device = Device.new
Device.find(1)
  ActiveRecord::RecordNotFound: Couldn't find Device with ID=1

From the description of :dependent => :nullify it doesn't sound like it should be deleting the device that was previously assigned. It doesn't do this if :dependent is not set.

Why should :dependent => :nullify delete objects like this when the default setting doesn't?

Reported by Chris Elledge · October 30th, 2008 @ 09:36 PM

State: resolved
Milestone: 2.x
Assigned to: Pratik Pratik
Importance: none

Activity

  1. Gregory Man
  2. labria
    labria

    Added a test to show the problem.

    November 10th, 2008 @ 05:24 PM

  3. labria
    labria

    I have found the source of it. The HasOneAssociation has a "replace" method. Inside it, it checks the dependent? method of the association, and if it finds it to be true, it destroys the old associated object.

    
    unless @target.nil? || @target == obj
      if dependent? && !dont_save
        @target.destroy unless @target.new_record?
        @owner.clear_association_cache
      else
        @target[@reflection.primary_key_name] = nil
        @target.save unless @owner.new_record? || @target.new_record?
      end
    end
    

    The problem is: the "dependent?" method only checks this:

    
    def dependent?
      @reflection.options[:dependent]
    end
    

    So, no matter what kind of :dependent key was used, it destroys the record. I'll try to add tests and fix the problem.

    November 10th, 2008 @ 05:41 PM

  4. labria
    labria
    • Tag changed from has_one, nullify to has_one, nullify, patch

    Here's the patch fixing the problem. What still remains is the fact that :destroy or :delete do not actually matter, each time #destroy is called.

    November 10th, 2008 @ 05:57 PM

  5. labria
    labria

    Fixed the case when destroy was called instead of delete. Tests included.

    November 10th, 2008 @ 07:10 PM

  6. Max Lapshin
    Max Lapshin

    +1 This should be fixed.

    November 10th, 2008 @ 08:14 PM

  7. Gregory Man
  8. Roy Man
  9. Pratik
    Pratik
    • Assigned user set to Pratik

    November 14th, 2008 @ 10:59 PM

  10. Pratik
    Pratik
    • State changed from new to incomplete

    I don't think the tests should be using stubbing here. Account has the following callback :

    
      before_destroy do |account|
        if account.firm
          Account.destroyed_account_ids[account.firm.id] << account.id
        end
        true
      end
    

    So that can be used here.

    March 6th, 2009 @ 06:55 PM

  11. Pratik
    Pratik

    Nevermind, I'll make the change and commit.

    Thanks.

    March 6th, 2009 @ 07:10 PM

  12. Repository
    Repository
    • State changed from incomplete to resolved

    (from [984bc7a614852944808739fae09a654b6e62872e]) Ensure replacing has_one associations respects the supplied :dependent option. [#1305 has_one dependent nullify deletes associated object on change state:resolved]

    Signed-off-by: Pratik Naik pratiknaik@gmail.com http://github.com/rails/rails/co...

    March 6th, 2009 @ 07:13 PM