我正在阅读Rails Devise gem
文档,并说:
如果页面可能没有设置current_user,那么:
if current_user.try(:admin?) # do something end
我试过没有问号
current_user.try(:admin)
它的工作方式与返回true
或false
的方式相同。
我错过了什么吗?有什么区别,我怎么能看到它?
答案 0 :(得分:2)
Ruby有点不寻常,因为它允许您在方法名称中包含各种字符,包括?
和!
。
它们对翻译没有特别的意义,但语言惯例是:
?
结尾的方法是疑问句 - 它们应该始终返回true或false。!
结尾的方法要么改变被调用的对象,要么引发异常。那为什么一点都重要?在这种特殊情况下,它并不重要,因为您的用户类具有ActiveRecord创建的@admin
实例变量的访问器 - 就像任何其他列一样。
如果没有,current_user.try(:admin)
总是会返回nil。请记住,在您提供访问者*之前,实例变量在Ruby中始终是私有的。
# Just a plain old Ruby class - not an ActiveRecord model
class User
def initialize
@admin = true
end
def admin?
@admin
end
end
User.new.try(:admin) # is always nil...
这是因为User
没有回复:admin
而.try
会阻止NoMethodError
而只会返回nil。
在普通的旧ruby类中,您将添加访问器以使实例变量@admin
可用:
class User
def initialize
@admin = true
end
attr_accessor :admin
end
这是做什么的:
class User
def initialize
@admin = true
end
# getter
def admin
@admin
end
# setter
def admin=(val)
@admin = val
end
end
ActiveRecord从您的数据库中读取架构,并使用元编程将自动魔术添加到模型类的访问器。它们比上面的例子复杂一点,但它的基本原理相同。这就是为什么你的用户模型响应#admin
。
答案 1 :(得分:1)
在这种情况下,可能没有功能差异。
我猜admin
是users
数据库表中的布尔字段。因此,user.admin
将返回true
或false
- 这里没有任何意外!
对于表中的每一列,Rails还将自动生成一个前缀为?
的关联方法。例如,如果您有一个列foo
,则会有一个方法foo?
- 根据true
的值返回false
或foo
例如,如果current_user.name == "Tom"
则current_user.name? == true
。如果current_user.name == nil
,则current_user.name? == false
。
在您的代码中使用?
方法很少必要,因为无论如何所有对象在ruby中都是“truthy”或“falsey”。但有时显示intent会有用,并使代码更容易阅读,因为很明显该值只是以布尔方式使用。
答案 2 :(得分:1)
默认情况下,可以使用或不使用问号(?)调用有关boolean的rails ActiveRecord对象属性。
按照惯例,如果添加?
,则更容易阅读,并且乍一看也表明它是布尔值。
因此,阅读此内容会给人一种用英语提问的印象。
因此,我的猜测是admin
是用户的布尔字段。
另外,上面的汤姆是非常正确的。