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 withdependent: :destroy
, and deleted if they're associated withdependent: :delete_all
.If the
:through
option is used, then the join records are deleted (rather than nullified) by default, but you can specifydependent: :destroy
ordependent: :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
How to Check a Word Is Already All Uppercase
Ruby: Accessing Rake Task from a Gem Without Rails
When to Use Memoization in Ruby on Rails
Differencebetween <%= ... %> and <% ... %> in Ruby on Rails
Convert Time to Other Timezone
Differencebetween Class and Klass in Ruby
Ruby on Rails Plural (Controller) and Singular (Model) Convention - Explanation
Why Isn't 'Method=' Treated the Same as Any Other Method
Call Controller from Rake Task
How to Get Haml to Work with Rails
Ruby Hash Default Value Behavior
Equivalent of "Continue" in Ruby
Circular Dependency Detected While Autoloading Constant User