如果: -> { status_change? && 完成的?红宝石?

lei*_*lei 3 ruby ruby-on-rails

我是红宝石新手。在 ruby​​_on_rails 项目中,我在模型的 rb 文件中找到以下代码

...    
before_validation :start_at, if: -> { status_change? && finished? }
...
Run Code Online (Sandbox Code Playgroud)

我不明白这里使用的语法...你能告诉什么if:->怎么讲啊?

谢谢

Mat*_*hew 7

哇,你的问题有很多......

Ruby 允许您将单行if语句放在一行的末尾。仅当if语句返回 true时才执行前面的语句。这些通常用于“保护条款”。但这并不是这里发生的事情......

如果 Ruby 可以准确推断出参数是什么,Ruby 还允许您去掉方法调用周围的括号。而不是输入sum(a, b)您可以键入sum a, b。这是使 Ruby 非常适合编写“领域特定语言”(如 Rake 和 ActiveRecord 的一部分)的原因之一。Thoughtbot 有一篇关于它们的好文章

因此,该行可以重写:

before_validation(:start_at, if: -> { status_change? && finished? })
Run Code Online (Sandbox Code Playgroud)

在这种情况下, before_validation 是一个ActiveRecord 回调。来自该链接,“回调是在对象生命周期的某些时刻被调用的方法。使用回调可以编写代码,这些代码将在创建、保存、更新、删除、验证或加载 Active Record 对象时运行数据库。”

在这种情况下,您拥有的是“条件回调”。该start_at方法(您可能会在模型文件的底部找到定义的方法,或者在其他地方,在代码库中搜索“def start_at”)只有在条件通过时才会被调用。

对于条件本身,status_change?并且finished?也是这两种方法。最后的问号是 Ruby 约定,表示此方法返回一个布尔值。该&&是布尔逻辑地说,整个条件将返回当且仅当两个真实status_change?finished?返回true。

所以,用简单的英语说明这行代码的作用:

  • 在 ActivRecord 检查模型是否有效之前
  • 运行start_at方法...
  • ...但前提是status_change?方法和finished?方法都评估为真

在幕后,它的工作方式是将“lambda”作为参数传递给方法。在这种情况下,它使用 Ruby 1.9 中引入的“stabby lambda”语法。查看The Ultimate Guide to Blocks, Procs and LambdasUsing Lambdas in Ruby了解更多信息。

  • 可能值得注意的是,条件必须作为过程传递给类方法,以便在验证时可以在实例的上下文中对其进行评估。(使用修饰符-if 是不可能的) (2认同)