Rails :dependent => destroy, want to call another action instead of destroy
Asked Answered
M

4

6

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...

Mockery answered 17/2, 2012 at 10:37 Comment(0)
M
3

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.

Massie answered 17/2, 2012 at 10:48 Comment(3)
I updated my first message and explain more... How to change the destroy method ?Mockery
Never mind if you saw my previous comment (deleted)... Phyo and Shingara have the right take.Massie
I'm sorry, but the problem is not for associations in my model. If I have only one model, I can't overwrite the destroy method to change its behaviour. This does nothing. Adding a before or after callback won't change the destroy: the item will be destroyed.Mockery
G
12

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.

Gentlefolk answered 17/2, 2012 at 10:49 Comment(0)
S
4

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
Shaft answered 17/2, 2012 at 10:48 Comment(0)
M
3

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.

Massie answered 17/2, 2012 at 10:48 Comment(3)
I updated my first message and explain more... How to change the destroy method ?Mockery
Never mind if you saw my previous comment (deleted)... Phyo and Shingara have the right take.Massie
I'm sorry, but the problem is not for associations in my model. If I have only one model, I can't overwrite the destroy method to change its behaviour. This does nothing. Adding a before or after callback won't change the destroy: the item will be destroyed.Mockery
C
1

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

Clark answered 11/12, 2013 at 15:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.