回调是如何调用的?

How are callbacks called?

回调的环境是什么?

例如,在 Rails 教程”(http://rails-4-0.railstutorial.org/book/modeling_users) 中标准 Ruby 的清单 6.20 中有:

class User < ActiveRecord::Base
  before_save { self.email = email.downcase }

"email"从何而来?我们在一个定义了 email 的函数中吗?或者实际上是 @email

此外,我们使用 self.email 而不是 @email(或者只是 email,如果它与 @email 相同)是否有重要原因?或者这只是风格上的,还是教学上的?

这里同时发生了几件事:

  1. 在保存模型实例的上下文中调用该块,因此块中的 self 是要保存的 User。该块还传递了一个参数,但您不必使用它。
  2. Ruby 中的局部变量没有显式声明,当您第一次尝试给它们赋值时,它们是隐式声明的。
  3. 方法调用的隐式接收者是self
  4. 但是局部变量优先于方法调用,因此增变器方法(例如 self.email=)需要一个显式接收器来将其与局部变量区分开来。
  5. 实例变量 (@email) 与 ActiveRecord 模型中的 属性 没有任何关系。
  6. ActiveRecord 对象的访问器(self.email 或者只是 email 如果没有 email 局部变量)和修改器方法 (self.email=) 使用属性,而不是实例变量。

所以这个:

before_save { self.email = email.downcase } # (1)

也可以写成:

before_save { |user| user.email = user.email.downcase } # (2)

甚至:

before_save { |user| user.send(:email=, user.send(:email).downcase) } # (3)

主要的功能区别是 (2) 要求 emailemail= 方法是 public.

回调 运行 在对象(在您的示例中为用户)范围内。 self.email=是一个对象方法,而@email是一个实例变量。

ActiveRecord 自动为相应数据库中的所有列创建方法(getter 和 setter)table(我假设您在 users table 中有 email 列) .

注意,使用 @email = 而不是 self.email = 将创建实例变量并且不会更新数据库中的列。