In rails, How to determine if a record was destroy

2019-04-21 06:26发布

I've got a record in my Rails app with an after_destroy hook that needs to do be aware why the record gets destroyed. More specifically, if the record is being destroyed in a cascade because its parent says dependent: :destroy, it needs to do things differently than if the record was individually destroyed.

What I tried to do is to see if its parent was destroyed?, only to figure out that dependent: :destroy callbacks are done before the parent is destroyed. Which makes sense because it should be able to fail. (i.e. restrict).

So, how do I do this?

2条回答
乱世女痞
2楼-- · 2019-04-21 07:10

Solution #1

If your model is simple enough and you don't need to invoke any callbacks in the child relation, you can just use dependent: delete_all in the parent.

Solution #2

For more complex scenarios you can use destroyed_by_association, which returns a ActiveRecord::Reflection::HasManyReflection object when it's part of cascade, or nil otherwise:

after_destroy :your_callback

def your_callback
  if destroyed_by_association
    # this is part of a cascade
  else
    # isolated deletion
  end
end

I just tried this in Rails 4.2 and it works.

Source: https://github.com/rails/rails/issues/12828#issuecomment-28142658

查看更多
放我归山
3楼-- · 2019-04-21 07:22

One way to do this is using the before_destroy callback in the parent object to mark all child objects as destroyed through parent destroy. Like his:

class YourClass
  before_destroy :mark_children

  ...
  ...

  def mark_children
    [:association1, :association2].each do |association|   # Array should inclue association names that hate :dependent => :destroy option
      self.send(association).each do |child|
        # mark child object as deleted by parent
      end
    end
  end
end

You can also use ActiveRecord Reflections to determine automaticly which associations are marked as :dependent => :destroy. Doing this is helpfull when you need this function in many classes.

查看更多
登录 后发表回答