Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

:dependent => :delete on belongs_to doesn't delete owner object

I have been checking options of belongs_to method and testing following behavior in Rails 3.2.7

As per above link the :dependent option states that

If set to :destroy, the associated object is destroyed when this object is. If set to :delete, the associated object is deleted without calling its destroy method.

As I understand the Author should be removed if Post is removed in following case:

class Post < ActiveRecord::Base
  belongs_to :author, :dependent => :delete
end

class Author < ActiveRecord::Base
  attr_accessible :name
  has_one :post

  before_destroy :log_author_removal

  private
    def log_author_removal
      logger.error('Author is getting removed')
    end

end

In console:

> Post.first
  Post Load (0.4ms)  SELECT "posts".* FROM "posts" LIMIT 1
 => #<Post id: 5, title: "Post 5", author_id: 3>
> p.delete
  SQL (197.7ms)  DELETE FROM "posts" WHERE "posts"."id" = 5
 => #<Post id: 5, title: "Post 5", author_id: 3> 
> Author.find(3)
  Author Load (0.5ms)  SELECT "authors".* FROM "authors" WHERE "authors"."id" = ? LIMIT 1  [["id", 3]]
 => #<Author id: 3, name: "Author 3"> 

However calling p.destroy deletes associated author.

Am I misunderstood above quoted statement?

like image 395
Amit Patel Avatar asked Sep 17 '12 11:09

Amit Patel


People also ask

What is the difference between dependent => destroy and dependent => Delete_all in Rails?

What is the difference between :dependent => :destroy and :dependent => :delete_all in Rails? There is no difference between the two; :dependent => :destroy and :dependent => :delete_all are semantically equivalent.

What does dependent destroy mean Rails?

If you set the :dependent option to: :destroy, when the object is destroyed, destroy will be called on its associated objects. :delete, when the object is destroyed, all its associated objects will be deleted directly from the database without calling their destroy method.

How does dependent destroy work?

dependent: :destroy Rails, when attempting to destroy an instance of the Parent, will also iteratively go through each child of the parent calling destroy on the child. The benefit of this is that any callbacks and validation on those children are given their day in the sun.

What is the difference between Has_one and Belongs_to?

They essentially do the same thing, the only difference is what side of the relationship you are on. If a User has a Profile , then in the User class you'd have has_one :profile and in the Profile class you'd have belongs_to :user . To determine who "has" the other object, look at where the foreign key is.


3 Answers

Yes, calling delete generally skips all callbacks that either you or rails set on destroying the record. These include callbacks like before_destroy and also destroying associated records.

Therefore if you call p.delete it will not do anything with the associated records.

When you call p.destroy it will:

  1. Call the before_destroy callback if set.
  2. Delete the object.
  3. If you set :dependent => :delete, it will simply delete the Author object. If you set it to :destroy it will repeat this whole process for the author object (callback & destroying its related records if applicable).
  4. Call the after_destroy callback if set.
like image 193
Jakub Hampl Avatar answered Sep 29 '22 23:09

Jakub Hampl


From what I understand :

:dependent => :destroy will trigger association.destroy if you call destroy on the object.

:dependent => :delete will trigger association.delete if you call destroy on the object.

In both cases, you have to call destroy on the parent object. The difference lies in th methos that is called on the child object. If you don't want to trigger destroy filters on the child object use :dependent => :delete. If you do want them, use :dependent => :destroy.

By quickly taking a look at the source here : https://github.com/rails/rails/blob/357e288f4470f484ecd500954fd17fba2512c416/activerecord/lib/active_record/associations/builder/belongs_to.rb#L68

We see that calling dependent will just create an after_destroy on the parent model, calling either delete or destroy on the child object. But in both cases, it creates an after_destroy.

like image 21
Anthony Alberto Avatar answered Sep 29 '22 22:09

Anthony Alberto


belongs_to association support both :delete and :destroy for :dependent. you can refer below link http://apidock.com/rails/v4.0.2/ActiveRecord/Associations/ClassMethods/belongs_to

calling delete skips all callbacks like before_destroy and as well won't delete associated records for association object as well.

Example

class Order < ActiveRecord::Base
has_one :project, :dependent => :delete
has_many :resources, :dependent => :delete
end

class Project < ActiveRecord::Base
belongs_to :order, :dependent => :delete
end

In above code,if project has been destroyed then order will as well deleted but resources in order won't delete but if we use

belongs_to :order, :dependent => :destroy

then resources attached with orders as well deleted on project destroy.

like image 33
Vaibhav Avatar answered Sep 29 '22 22:09

Vaibhav