Question

I have a has_many :through model that works perfectly.

  has_many :varietals
  has_many :grapes, :through => :varietals, :dependent => :destroy

I would like to call another action instead of :destroy. In fact, I don't want to nullify the item OR destroy it, I want to update the record status field from 1 to 0 instead of destroy the record.

How to call a custom method instead of destroy ? I suppose I can do that in the model itself... Thanks.

Where to put this method ? In the master model or in the model where the record will be destroyed ?

EDIT:

I'm sorry but I think I didn't enough explain my problem. My problem is not only to so something after the master model is destroyed. I want to custom the destroy action in the Varietal model itself even if the master record is not destroyed.

Something like:

class Varietal < ActiveRecord::Base

    private
      def destroy
        self.update_attributes(:status => 0)
      end
end

Actually this action is not called...

Was it helpful?

Solution

has_many :dependent is limited to only a few options. According to the documentation:

:dependent If set to :destroy all the associated objects are destroyed alongside this object by calling their destroy method. If set to :delete_all all associated objects are deleted without calling their destroy method. If set to :nullify all associated objects’ foreign keys are set to NULL without calling their save callbacks. If set to :restrict this object raises an ActiveRecord::DeleteRestrictionError exception and cannot be deleted if it has 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.

It looks like you would need to alter the destroy method to update the status field.

OTHER TIPS

You can use before_destroy to put your custom logic there. E.g.,

before_destroy :reset_status

def reset_status
  ...
end

Check here for more details.

You just need add a callback on before_destroy or after_destroy and manipulate your associations. By example

after_destroy :do_on_grapes

def do_on_grapes
  grapes.map(&:to_do)
end

I believe that good approach to solve your problem is to provide a custom destroy method. There are several responses to questions like these, but you should keep in mind that ActiveRecord and Relationships like:

class Image < ActiveRecord::Base
  has_many :comments, dependent: :destroy

use callback mechanisms that trigger destroy chaining to your relations, too. Usually you should preserve this mechanism and add it to your custom implementation. E.g.

  def destroy
    self.update deleted_at: Time.now
    run_callbacks :destroy
  end

You can read this post, too: Triggering dependent: :destroy with overridden destroy-method

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top