如何调用回调?

时间:2018-04-26 21:48:22

标签: ruby-on-rails ruby callback before-save

回调的环境是什么?

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

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

“电子邮件”来自哪里?我们是否在定义email的函数中?或者实际上是@email

另外,我们使用self.email而不是@email(或仅email如果它与@email相同)有一个重要原因吗?或者只是风格或教学?

2 个答案:

答案 0 :(得分:3)

这里有几件事情在这里:

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

    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=方法公开。

答案 1 :(得分:0)

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

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

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