In my project there are many models with has_many
association and dependant: :destroy
flag. Also, each model have other belong_to
associations with the dependant: :destroy
flag. This models are nested between each other so when a destroy
is executed on the top one, Rails triggers cascading destroy on children models.
Apart from that, models have callbacks
that execute before_destroy
.
The following represents what I described above:
class Model1Example < ActiveRecord::Base
has_many :model2_examples, :dependent => :destroy
belongs_to :other1_example, :dependent => :destroy
belongs_to :other2_example, :dependent => :destroy
end
class Model2Example < ActiveRecord::Base
belongs_to :model1_example
has_many :model3_examples, :dependent => :destroy
belongs_to :other3_example, :dependent => :destroy
belongs_to :other4_example, :dependent => :destroy
before_destroy :update_something_on_model1
before_destroy :check_some_inconsistence
end
class Model3Example < ActiveRecord::Base
belongs_to :model2_example
belongs_to :other5_example, :dependent => :destroy
belongs_to :other6_example, :dependent => :destroy
before_destroy :update_something_on_model2
before_destroy :check_some_inconsistence
end
Given that on average Model2Example
holds about 100+ instances of Model3Example
when the Model1Example
destroy
is triggered many SQL queries are triggered (10k+) because deletion is record by record and also all rules are executed for every instance...and this takes a lot more than what a user could wait for such a simple action.
I could fix this performance issue by using dependant: :delete_all
on the has_many
associations instead, because I don't really care that all this rules are executed when I trigger Model1Example
destroy
.
But the problem is that when I execute (from elsewhere in the app) a Model2Example
destroy
is in my interest that all rules are executed (specially Model3Example
rules for each instance), and the previous mentioned approach brakes this.
Is there a "Rails way" to achieve a performance improvement for this case? Or should I just use SQL for Model1Example
deletion?
Also, if I have to use this approach and I wanted to check some basic stuff before destroying Model1Example
, where is the best place to do this validation? controller?