Ruby on Rails的model有email属性,那么self.email :email和email有什么区别?

最近在看railstutorial
通过rails g model User name:string email:string生成的model随着教程逐渐变成了以下的德行:

class User < ApplicationRecord
  before_save { self.email = email.downcase }
  validates :name,  presence: true, length: { maximum: 50 }
  #VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
end

这段代码里的self.email , email 以及 :email分别什么意思,有什么区别?
如果把 validates :email, ... 改为 validates self.email, ...
为什么会报 NoMethodError: NoMethodError: undefined method 'email'

阅读 2.8k
1 个回答
  • before_save { self.email = email.downcase }

这里面的 self.email 表示 当前对象 的 email属性;email.downcaseemail 表示调用一个 email 方法(ActiveRecord 自动为你生成的);
这行代码的意思表示:一个 User 实例对象在保存之前(before_save),email 转换成小写;
你的疑问可能是:什么时候用 self ,什么时候不用?
答案:绝大多数情况下都不用 self ,你遇到的这种情况是唯一一种需要显示使用 self 的情况。

  • validates :email, ... 改为 validates self.email, ...

validates 是一个 类宏(class macro),类宏中的 self 表示当前类对象本身(User),当前类 User 对象(类对象本身)并没有 email 方法(当前类 User 有一个实例方法 email,是 ActiveRecord 为你生成的,上面解释过了),所以报错;
这行代码的意思是:一个 User 实例对象 save 或者 update 之前,需要验证 email 属性;如果改成了 validates self.email, ... ,就代表验证 User 类对象本身的 email 方法,由于 User 类对象本身并没有 email 方法,所以 NoMethodError

PS:建议研读下 《Ruby 元编程》(中文版第二版早已经出版了),就会对 ruby 这些本质的东西有一个更透彻的理解;如果觉得 Ruby 中好多的方法都不知道怎么用,DHH 推荐的 《The Ruby Way: Solutions and Techniques in Ruby Programming》也是一本高大全的书;镐头书《Programming Ruby》和 David Flanagan 的《The Ruby Programming Language》也是两本非常好的 ruby 全解(尽管这两本已经有些过时,但对你没影响);

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进