是否有任何方法只在某些情况下禁用after_find

时间:2017-11-16 10:25:03

标签: ruby-on-rails ruby activerecord callback

我在我的模型中使用after_find,但在某些情况下想要禁用。 我正在使用 .where 仍然在after_find运行但是在文档中它表示它仅适用于以下方法。为什么会这样?

all
first
find
find_by
find_by_*
find_by_*!
find_by_sql
last

我的api(葡萄框架)是

delete '/delete_user' do
  user_id = params[:user_id] #authenticate_current_user!
  @user_profile = ::UserProfile.where(user_id: user_id).
  @user_profile.destroy_all
end

1 个答案:

答案 0 :(得分:1)

after_find来电未调用where回调。您的destroy_all电话会调用它。 destroy_all将实例化每个UserProfile对象(及其关联对象),并逐个调用其destroy方法。

如果要立即删除所有UserProfile个对象,而不实例化它们(并跳过所有回调),则可以调用:

UserProfile.where(user_id: user_id).delete_all

有关destroy_all and delete_all之间差异的更多信息可以在StackOverflow的其他答案中找到,但您关心的差异是:

  1. 它不会实例化记录
  2. 它不会删除关联的对象
  3. 它不会调用任何回调
  4. 我建议你不要以after_find的方式使用它。有lots of ways to skip callbacksalmost nobody uses after_find。 (例如,与after_create相比)

    跳过after_find回调的选项有限。这样做没有built-in Rails methods。 (除了如上所述)如果你绝对必须保持回调,那么你最好的办法就是给回调定义添加一个条件:

    after_find :foo, if: -> { <some logic> }
    

    如果您使用类似的条件,那么您必须开始考虑如何在多线程环境中读取和设置该变量,以及如何在不创建竞争条件的情况下处理并发请求,并且它会向您发送一条丑陋的路径通过不按照您描述的方式使用after_find可以更好地处理。