2

我正在将一个项目从 Rails 2.3.2 升级到 2.3.15。似乎exists?现在可以将其视为查找器,这意味着诸如after_find现在是来自exists?.

在 2.3.2exists?中没有触发回调到after_find. 除了在 github 上明确命名此策略更改的提交之外,我无法找到可读的更改日志。

有人可以确认在 2.3.2exists?中没有调用after_find(应该存在)并且在 2.3.15 中调用了吗?

如果是这种情况,是否有一种干净的 Rails 方法来隔离after_find调用?我需要在真正找到之后执行一些代码,而不是在exists?.

作为临时解决方法,我正在尝试将其作为模型中的第一行after_find

return unless self.has_attribute?(:some_attrib_your_model_uses_in_after_find)
4

2 回答 2

0

我发现了三种方法可以做到这一点,它们都不令人满意,但至少有两种方法可以可靠地工作,即使它们在设计上令人惊讶并且可能会在未来产生一些非常微妙的错误。

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 `存在?
(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) 使模型 Eager-Load

有些人可能想要这样做,2.3.15 ActiveRecord README 提示它:

after_find :eager_load, 'self.class.announce(#{id})'

我不想给数据库带来更多的负担。在许多情况下调用exists?的目的是进行简单的单列查找。执行整个模型的预加载以及可能的关联只是为了进行exists?调用将导致性能下降。

于 2013-01-16T18:25:00.287 回答
0

这个答案对你有帮助吗?

升级到 rails3 后 after_find 回调中断

head rails 2.3 分支应该接近于 rails 3 中存在的内容。我认为很多类似的重大变化发生在 2.3.12 或 2.3.14 前后。IIRC 这样做是为了简化对 Rails 3 的升级。

于 2013-01-16T18:53:50.523 回答