如果在Ruby中有一个状态变化并且已完成的情况,你会如何称呼它?

3

我是一个 Ruby 的新手。

在一个 Ruby on Rails 项目中,我在 models 文件夹下的一个 rb 文件中发现了以下代码:

...    
before_validation :start_at, if: -> { status_change? && finished? }
...

我不理解这里使用的语法...你能告诉我这里的if:->是什么意思吗?
谢谢。

1
这是传递给 before_validation关键字参数。参数值是一个 proc 或 lambda。 - Stefan
if:表示符号:if。如果您有一个哈希表,其中键是符号,则可以将其写为{:foo => 46, :bar => 16}或更时髦的{foo: 46, bar: 16}->表示lambda,即具有检查参数数量的Proc。如果有人调用它并错误地传递了参数,则会收到RuntimeError。 - user1934428
@Stefan 并不是一个关键字参数,因为该方法的签名没有将其定义为关键字参数def before_validation(*args, &block) - engineersmnky
1个回答

8

哇,你的问题涉及很多内容...

Ruby允许你在一行代码的结尾放置单行if语句。如果if语句返回true,则执行前面的语句。这些通常用于"守卫条件"。但这不完全是这里正在发生的事情...

Ruby还允许你省略方法调用周围的括号,如果它可以推断出确切的参数。例如,你可以输入sum a, b而不是sum(a, b)。这是使Ruby适合编写像Rake和ActiveRecord的"特定领域语言"之一。Thoughtbot有一篇好文章介绍了这方面的内容。

因此,该行代码可以重写为:

before_validation(:start_at, if: -> { status_change? && finished? })

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

在这个例子中,你看到的是一个“条件回调函数”。start_at 方法(你可能会在模型文件底部找到该方法的定义,或者其他地方,在代码库中搜索“def start_at”)仅在条件通过时才会被调用。

关于条件本身,status_change?finished? 也都是方法。问号表示这两个方法返回布尔值。而 && 是布尔逻辑运算符,它表示只有当 status_change?finished? 都返回 true 时,整个条件语句才会返回 true。

因此,简单来说,这行代码的作用是:

  • 在 ActivRecord 检查模型是否有效之前
  • 运行 start_at 方法...
  • ...但仅当 status_change?finished? 方法都返回 true 时

在底层,这是通过将“lambda”作为参数传递给方法来实现的。在本例中,它使用了 Ruby 1.9 中引入的“stabby lambda”语法。请查看块、Procs 和 Lambdas 的终极指南在 Ruby 中使用 Lambdas以获取更多信息。


2
值得注意的是,条件必须作为proc传递给类方法,以便在验证时在实例上下文中进行评估(这是使用修改器if不可能实现的)。 - Stefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接