ActiveRecord如何实现`:if => ......`关于验证

时间:2010-12-22 11:32:10

标签: ruby-on-rails validation activerecord ruby-on-rails-2

我一直在查看ActiveRecord源代码以了解:if => proc_or_method_name如何处理ActiveRecord验证,但源中:if的唯一实例是在解释如何调用该功能的注释中

例如,您可以在模型中使用如下所示的行:

validates_presence_of :name, :if => :nameable?

如果nameable?方法返回给定模型的真值,则仅检查验证。

这个功能实际定义在哪里,因为我在(Rails2)源中的任何地方都找不到这种行为?

2 个答案:

答案 0 :(得分:3)

从Rails 3开始,ActiveRecord回调在active_record/callbacks.rb中定义,但由于ActiveRecord模型继承自ActiveModel,因此您还应该查看active_model/callbacks.rb文件。

回调功能本身是一个单独的组件。事实上,过滤器之前/之后的ActionController实际上就是回调。 因此,回调系统是ActiveSupport::Callbacks中定义的模块。

将这3个部分合并在一起,就可以获得ActiveRecord回调功能。

答案 1 :(得分:3)

:if文件中检查activesupport\lib\active_support\callbacks.rb选项。

调用方法should_run_callback以检查是否应该执行回调。

还要看一下如何处理回调链,从同一文件中的run_callbacks方法开始。

该文件的v2.3.8中的一些代码是:

def should_run_callback?(*args)
  [options[:if]].flatten.compact.all? { |a| evaluate_method(a, *args) } &&
  ![options[:unless]].flatten.compact.any? { |a| evaluate_method(a, *args) }
end

以下是我发现的方式(万一有人感兴趣):

  1. 从github下载Rails v2.3.8并解压缩。
  2. grepp'ed for :if in all .rb files
  3. activerecord/CHANGELOG中,找到了一条评论:
    为所有验证添加了:if选项,可以使用块或方法指针来确定是否应该运行验证。 #1324 [Duane Johnson / jhosteny]。
  4. Google为此发表评论。在google cache
  5. 中找到它
  6. 发现评论/添加是由david于05/21/05 10:57:18进行的。
  7. 日期为2005-05-21 rails github history on page 546
  8. 了解:if如何运作
  9. 发现v2.3.8中不再存在提交的提交代码。必须找到该代码的最新位置
  10. 再次
  11. grepp'ed :if然后浏览每个感觉“好”的文件。来到activesupport/lib/active_support/callbacks.rb
  12. 在文件中搜索了:if,并且只在方法should_run_callback中的一个位置找到了它。
  13. 发表回答
  14. 手指交叉,等待赏金。 :d
  15. 这很有趣!