最近在看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'
?
before_save { self.email = email.downcase }
这里面的
self.email
表示 当前对象 的email
属性;email.downcase
的email
表示调用一个 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 全解(尽管这两本已经有些过时,但对你没影响);