我正在将一个项目从 Rails 2.3.2 升级到 2.3.15。看起来 exists?
现在可以被视为查找器,这意味着 after_find
等函数现在是 exists?
的回调。
在 2.3.2 中 exists?
没有触发对 after_find
的回调。除了在 github 上明确命名此策略更改的提交之外,我无法找到可读的更改日志。
有人可以确认 存在吗?
没有在 2.3.2 中调用 after_find
(它应该存在)而在 2.3.15 中调用了?
如果是这种情况,是否有一种干净的 Rails 方法来隔离 after_find
调用?我需要在真正找到之后执行一些代码,而不是在 exists?
之后执行。
作为临时解决方法,我正在尝试将其作为我模型的 after_find
中的第一行:
return unless self.has_attribute?(:some_attrib_your_model_uses_in_after_find)
最佳答案
我发现了三种方法可以做到这一点,虽然它们都不令人满意,但至少有两种方法可以可靠地工作,即使它们在设计上令人惊讶并且可能会在过程中产生一些非常微妙的错误。
A) 如果缺少您要使用的属性则返回
def after_find
# What a flaky way to ruin your code:
return unless self.has_attribute?(:some_attrib_your_model_uses_in_after_find)
@amazing_pain = @some_attrib_your_model_uses_in_after_find + 1
end
B) Grep 整个调用栈
(祈祷存在?因为你认为它存在)
我很不好意思将它作为一个选项发布,但很高兴看到您可以使用 caller
可用的字符串数组做什么。我们只希望 caller
不会更改格式。
从控制台使用 2.3.15,我模型的 after_find() 的调用堆栈是:
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.15/lib/active_record/callbacks.rb:347:in `send' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.15/lib/active_record/callbacks.rb:347:in `callback' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.15/lib/active_record/base.rb:1687:in `send' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.15/lib/active_record/base.rb:1687:in `instantiate' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.15/lib/active_record/base.rb:665:in `find_by_sql' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.15/lib/active_record/base.rb:665:in `collect!' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.15/lib/active_record/base.rb:665:in `find_by_sql' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.15/lib/active_record/base.rb:1582:in `find_every' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.15/lib/active_record/base.rb:1539:in `find_initial' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.15/lib/active_record/base.rb:696:in `exists?' (irb):2:in `irb_binding' /usr/lib/ruby/1.8/irb/workspace.rb:52:in `irb_binding' /usr/lib/ruby/1.8/irb/workspace.rb:52
C) Make the Model Eager-Load
Some people might want to do this, an the 2.3.15 ActiveRecord README hints at it:
after_find :eager_load, 'self.class.announce(#{id})'
我不想给数据库增加不必要的负担。在许多情况下,调用 exists?
的目的是进行简单的单列查找。执行整个模型及其关联的预先加载只是为了执行 exists?
调用将导致性能下降。
关于ruby-on-rails - 如何防止 Rails `exists?` 调用 `after_find`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14364556/