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

发布于 2024-10-08 11:27:57 字数 359 浏览 1 评论 0原文

我一直在浏览 ActiveRecord 源代码以了解 :if => 是如何实现的。 proc_or_method_name 适用于 ActiveRecord 验证,但源代码中 :if 的唯一实例位于解释如何调用该功能的注释中。

例如,您可以在模型中包含如下行:

validates_presence_of :name, :if => :nameable?

并且仅当 nameable? 方法返回给定模型的真值时才会检查验证。

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

I've been looking through the ActiveRecord source to find out how :if => proc_or_method_name works on ActiveRecord validations, but the only instances of :if in the source are in the comments explaining how the feature should be called.

For example, you can have a line like the following in a model:

validates_presence_of :name, :if => :nameable?

and the validation only gets checked if the nameable? method returns a truthy value for the given model.

Where is this functionality actually defined, as I can't find this behaviour anywhere in the (Rails2) source?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

如日中天 2024-10-15 11:27:57

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

调用方法 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. 在所有 .rb 文件中对 :if 进行 grep 编辑
  3. activerecord/CHANGELOG 中,找到一条注释,其中提到:

    向所有验证添加了 :if 选项,这些验证可以使用块或方法指针来确定是否应运行验证。 #1324 [杜安·约翰逊/jhosteny]。
  4. Google 搜索该评论。在 Google 缓存
  5. 发现评论/添加是由 david 于 05/21/05 10:57:18 发表的,
  6. 位于日期 2005-05-21 rails github 历史记录第 546 页
  7. 了解 :if 的工作原理
  8. 发现提交引用的代码不再存在于v2.3.8。必须
  9. 再次找到该代码的最新位置 grep'ed :if 并浏览每个感觉“良好”的文件。来到activesupport/lib/active_support/callbacks.rb
  10. 在文件中搜索:if,只在一个位置找到了它,在方法should_run_callback.
  11. 发布答案
  12. 交叉手指并等待赏金。 :D

很有趣!

The :if option is checked for in the file activesupport\lib\active_support\callbacks.rb.

The method should_run_callback is called to check if the callback should be executed or not.

Look also at how the callback chain is processed, starting from the run_callbacks method in the same file.

Some code from v2.3.8 of that file is:

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

And here is how I found out (in case anyone is interested):

  1. Downloaded Rails v2.3.8 from github and unzipped it.
  2. grepp'ed for :if in all .rb files
  3. In a activerecord/CHANGELOG, located a comment that mentioned:

    Added the :if option to all validations that can either use a block or a method pointer to determine whether the validation should be run or not. #1324 [Duane Johnson/jhosteny].
  4. Google'd for that comment. Found it in a google cache.
  5. Found that the comment/addition was made on 05/21/05 10:57:18 by david
  6. Located date 2005-05-21 on rails github history on page 546:
  7. Got an inkling of how the :if works
  8. Found that the code that commit referred to was no longer existing in v2.3.8. had to find latest location of that code
  9. grepp'ed :if again and went though each file that felt "good". came to activesupport/lib/active_support/callbacks.rb
  10. searched for :if in the file and it was found in only one location, in the method should_run_callback.
  11. Posted answer
  12. Crossed fingers and waited for bounty. :D

That was fun!

永言不败 2024-10-15 11:27:57

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

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

将这 3 部分合并在一起,您将获得 ActiveRecord 回调功能。

As of Rails 3, ActiveRecord callbacks are defined in active_record/callbacks.rb, but because an ActiveRecord model inherits from ActiveModel, then you should also look at the active_model/callbacks.rb file.

The Callback feature itself is a separate component. In fact, ActionController before/after filters are callbacks, actually.
For this reason, the callback system is a module defined in ActiveSupport::Callbacks.

Merge altogether these 3 pieces and you get the ActiveRecord callbacks feature.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文