基于rails的schedule网站开发(13):用send 方法改写authenticated?(...)

来源:互联网 发布:蚁群算法原理怎么改进 编辑:程序博客网 时间:2024/06/05 22:33

abstract:
元编程(metaprogramming)——send方法

title 1
title 2
title 3

send方法的作用是在指定的对象上调用指定的方法
例如,在下面的控制台会话中,我们在一个 Ruby 原生对象上调用 send 方法,获取数组的长度:

$ rails console>> a = [1, 2, 3]>> a.length=> 3>> a.send(:length)=> 3>> a.send('length')=> 3

可以看出,把 :length 符号或者 ‘length’ 字符串传给 send 方法的作用和在对象上直接调用 length 方法的作用一样。再看一个例子,获取数据库中第一个用户的 activation_digest 属性:

>> user = User.first>> user.activation_digest=> "$2a$10$4e6TFzEJAVNyjLv8Q5u22ensMt28qEkx0roaZvtRcp6UZKRM6N9Ae">> user.send(:activation_digest)=> "$2a$10$4e6TFzEJAVNyjLv8Q5u22ensMt28qEkx0roaZvtRcp6UZKRM6N9Ae">> user.send('activation_digest')=> "$2a$10$4e6TFzEJAVNyjLv8Q5u22ensMt28qEkx0roaZvtRcp6UZKRM6N9Ae">> attribute = :activation>> user.send("#{attribute}_digest")=> "$2a$10$4e6TFzEJAVNyjLv8Q5u22ensMt28qEkx0roaZvtRcp6UZKRM6N9Ae"

注意最后一种调用方式,我们定义了一个 attribute 变量,其值为符号 :activation,然后使用字符串插值构建传给 send 方法的参数。attribute 变量的值使用字符串 ‘activation’ 也行,不过符号更便利。不管使用什么,插值后,”#{attribute}_digest” 的结果都是 “activation_digest”。
基于上述对 send 方法的介绍,我们可以把 authenticated? 方法改写成:

def authenticated?(remember_token)  digest = self.send('remember_digest')  return false if digest.nil?  BCrypt::Password.new(digest).is_password?(remember_token)end

以此为模板,我们可以为这个方法增加一个参数,代表摘要的名字,然后再使用字符串插值,扩大这个方法的用途:

def authenticated?(attribute, token)  digest = self.send("#{attribute}_digest")  return false if digest.nil?  BCrypt::Password.new(digest).is_password?(token)end

(我们把第二个参数的名字改成了 token,以此强调这个方法的用途更广。)因为这个方法在用户模型内,所以可以省略 self,得到更符合习惯写法的版本:

def authenticated?(attribute, token)  digest = send("#{attribute}_digest")  return false if digest.nil?  BCrypt::Password.new(digest).is_password?(token)end

现在我们可以像下面这样调用 authenticated? 方法实现以前的效果:
user.authenticated?(:remember, remember_token)

在书中的这种改变,是为了让uthenticated?(…)方法可以用于验证登陆用户是否是cookie中保持的用户,又可以用于验证用户是否是邮箱验证过的用户。

0 0
原创粉丝点击