Callback before destroy and before associated records destroyed

房东的猫 提交于 2019-12-12 05:27:31

问题


I have the following model:

class PhoneNumber < ActiveRecord::Base
  has_many :personal_phone_numbers, :dependent => :destroy
  has_many :people, :through => :personal_phone_numbers
end

I want to set up an observer to run an action in a delayed_job queue, which works for the most part, but with one exception. I want the before_destroy watcher to grab the people associated with the phone number, before it is destroyed, and it is on those people that the delayed job actually works.

The problem is, when a phone number is destroyed, it destroys the :personal_phone_numbers record first, and then triggers the observer when it attempts to destroy the phone number. At that point, it's too late.

Is there any way to observe the destroy action before dependent records are deleted?


回答1:


While this isn't ideal, you could remove the :dependent => :destroy from the personal_phone_numbers relationship, and delete them manually in the observer after operating on them.

However, I think that this issue might be showing you a code smell. Why are you operating on people in an observer on phone number. It sounds like that logic is better handled in the join model.




回答2:


Use alias_method to intercept the destroy call?

class PhoneNumber < ActiveRecord::Base
  has_many :personal_phone_numbers, :dependent => :destroy
  has_many :people, :through => :personal_phone_numbers

  alias_method :old_destroy, :destroy

  def destroy(*args)
    *do your stuff here*
    old_destroy(*args)
  end
end



回答3:


It sounds like your problem in a nutshell is that you want to gather and act on a collection of Person when a PersonalPhoneNumber is destroyed. This approach may fit the bill!

Here is an example of a custom callback to collect Person models. Here it's an instance method so we don't have to instantiate a PersonalPhoneNumberCallbacks object in the ActiveRecord model.

class PersonalPhoneNumberCallbacks
  def self.after_destroy(personal_phone_number)
    # Something like people = Person.find_by_personal_phone_number(personal_phone_number)
    # Delayed Job Stuff on people
  end
end

Next, add the callback do your ActiveRecord model:

class PersonalPhoneNumber < ActiveRecord::Base
  after_destroy PictureFileCallbacks
end

Your after_destroy callback will have the model passed down and you can act on its data. After the callback chain is complete, it will be destroyed.

References

  • http://guides.rubyonrails.org/active_record_validations_callbacks.html#relational-callbacks
  • http://guides.rubyonrails.org/association_basics.html#association-callbacks



回答4:


You can use a before_destroy callback in the model, then grab the data and do whatever operation you need to before destroy the parent. Something like this example should be what you are looking for:

class Example < ActiveRecord::Base
before_destroy :execute_random_method


private

def execute_random_method
  ...
end
handle_asynchronously :execute_random_method


来源:https://stackoverflow.com/questions/11654014/callback-before-destroy-and-before-associated-records-destroyed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!