在学习rails的过程中, 遇到了下面这样一段代码,里面的self.remember_token
让我有些找不到方向。
class User < ActiveRecord::Base
attr_accessor :remember_token
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
def User.new_token
SecureRandom.urlsafe_base64
end
end
乍看之下, self.remember_token
是一个变量,还用了等号赋值。
但其实这里的是一个实例方法。
在class里定义了attr_accessor :remember_token
, 而attr_accessor :remember_token
等价于:
def remember_token
@remember_token
end
def remember_token=(value)
@remember_token = value
end
第一个是读方法(getter), 第二个是写方法(setter)
注意第二个方法remember_token=
, 这里有一个=
再来看一下那行奇怪的代码, self.remember_token = User.new_token
其实就是调用了上面的setter方法, self.remember_token = (User.new_token)
这里的方法调用, 看上去就和赋值一模一样了
而之后User.digest(remember_token)
中的remember_token
则是调用了getter方法
这里又牵涉到self
的用法, 关于self
:
- self在class内, 其指的是class本身
- self在def内, 则表示类的实例
所以在def内, 使用self.method
调用一个实例方法。
ruby贯彻了DRY, 在大部分情况下, 我们都可以不使用self
, 隐式调用一个实例方法,
但是, setter方法不在此列, 也就是说setter方法需要显式调用
而这里的
-
self.remember_token = User.new_token
是一个显式调用 -
User.digest(remember_token)
是一个隐式调用
其实这里是可以使用实例变量来替代的:
def remember
@remember_token = User.new_token
update_attribute(:remember_digest, User.digest(@remember_token))
end
至此, 让我也对实例变量和访问器有了更全面的了解