Rails: How to Use Dependent: :Destroy in Rails

Rails: How to use dependent: :destroy in rails?

Add cascading delete to your EmpGroup model:

class EmpGroup < ActiveRecord::Base
has_many :emp_group_members, dependent: :delete_all
end

Or

Are you calling delete method? you should call destroy instead.
Use .destroy

Where to use dependent: :destroy

(1) In User model, has_many :receipts, dependent: :destroy

If user is destroyed then its associated receipts will be destroyed as well.

(2) In Receipt model, belongs_to :user, dependent: :destroy

If receipt is destroyed then its parent user will be destroyed, not other associated receipts would not be destroyed but would be orphaned. According to docs

This dependent: option should not be specified when belongs_to is used in
conjunction with a has_many relationship on another class because of
the potential to leave orphaned records behind.

Default dependent action when calling destroy in ActiveRecord / Rails

Your description is correct. But you should be aware that the subscribers records will be orphaned. If they are set up with a had_many relation, as you show, then each subscriber record contains a foreign key that is the id of the StackOverflowQuestion record, which will no longer exist after you destroy it. So it will point to an invalid record.

Rails: dependent: :destroy - How does this work?

You probably want :nullify. See the Rails docs for has_many.

:dependent controls what happens to the associated objects when their owner is destroyed. Note that these are implemented as callbacks, and Rails executes callbacks in order. Therefore, other similar callbacks may affect the :dependent behavior, and the :dependent behavior may affect other callbacks.

:destroy causes all the associated objects to also be destroyed.

:delete_all causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).

:nullify causes the foreign keys to be set to NULL. Callbacks are not executed.

:restrict_with_exception causes an exception to be raised if there are any associated records.

:restrict_with_error causes an error to be added to the owner if there are any associated objects.

If using with the :through option, the association on the join model must be a belongs_to, and the records which get deleted are the join records, rather than the associated records.

How to avoid N+1 queries in rails dependent destroy?

You can use

dependent: delete_all

which creates a single SQL query to delete the associated records, but any before_destroy after_destroy callbacks will not be called as no destroy method is going to be called.

If you're using Postgres you will need to pass the cascade flag in your origin migration on the foreign key for this to work

add_foreign_key :some_table, :related_table, on_delete: cascade

Dependent: :destroy only to the 2nd degree in has many through association

You can just delete the items, just add dependent: :destroy to has_many :items.

class Collection < ApplicationRecord
has_many :searches, through: :items
has_many :items, dependent: :destroy
end

After destroying a collection, the item is destroyed but the search will remain.

second solution

You could even apply dependent: :nullify to has_many :searches - getting the same result.

class Collection < ApplicationRecord
has_many :searches, through: :items, dependent: :nullify
has_many :items
end

From the docs:

collection.delete(object, …)

Removes one or more objects from the collection by setting their foreign keys to NULL. Objects will be in addition destroyed if they're associated with dependent: :destroy, and deleted if they're associated with dependent: :delete_all.

If the :through option is used, then the join records are deleted (rather than nullified) by default, but you can specify dependent: :destroy or dependent: :nullify to override this.

Difference between dependent destroy vs dependent delete on Rails Active Record

Yes, both will delete the database records but doing it in a different way.

You can check the answer for this question here:

Rails :dependent => :destroy VS :dependent => :delete_all

Basically dependent: :delete will execute the delete for the dependent records directly on the database without executing any activerecod validations or callbacks.

While dependent: :destroy will instantiate all the dependent records and execute a :destroy for each object (executing validations and callbacks).

How it works - `belongs_to :user, dependent: :destroy`

"has_many" 

A teacher "has_many" students. Every student has only one teacher, but every teacher has many students. This means that there is a foreign key, or teacher_id on the student referencing to what teacher they belong to.

"belongs_to" 

A student "belongs_to" a teacher. Every teacher has many students, but every student has only one teacher. Again, there is the foreign key on the student referencing to what teacher they belong.

Let's work this out an using this student / teacher concept.

Teacher Model

class Teacher < ActiveRecord::Base
has_many :students, dependent: :destroy
end

Student Model

class Student < ActiveRecord::Base
belongs_to :teacher
end

Assuming these models then

Teacher.destroy 

Will delete the instantiated teacher and all the students that were associated to that teacher.

For example

Teacher.find(345).destroy 

Would destroy the record of the teacher with the ID of 345 and destroy all the associated students with that teacher.

Now to the heart of the question, what happens when my models look like this?

Teacher Model

class Teacher < ActiveRecord::Base
has_many :students, dependent: :destroy
end

Student Model

class Student < ActiveRecord::Base
belongs_to :teacher, dependent: :destroy
end

If I were to call

Student.destroy

This would destroy the instantiated student and that student's associated teacher. However to my knowledge (and according to the docs) this would not destroy any other students related to that teacher, leaving them 'orphaned'.

Here is a quote from the Ruby docs on this 1

If set to :destroy, the associated object is destroyed when this object is. This option should not be specified when belongs_to is used in conjunction with a has_many relationship on another class because of the potential to leave orphaned records behind.



Related Topics



Leave a reply



Submit