为什么我们在这个rails try块中需要问号?

时间:2016-05-16 15:53:14

标签: ruby-on-rails ruby syntax devise

我正在阅读Rails Devise gem文档,并说:

  

如果页面可能没有设置current_user,那么:

     

if current_user.try(:admin?) # do something end

我试过没有问号

current_user.try(:admin)

它的工作方式与返回truefalse的方式相同。

我错过了什么吗?有什么区别,我怎么能看到它?

3 个答案:

答案 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。

ActiveRecord和访问者:

在普通的旧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)

在这种情况下,可能没有功能差异。

我猜adminusers数据库表中的布尔字段。因此,user.admin将返回truefalse - 这里没有任何意外!

对于表中的每一列,Rails还将自动生成一个前缀为?的关联方法。例如,如果您有一个列foo,则会有一个方法foo? - 根据true的值返回falsefoo

例如,如果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是用户的布尔字段。

另外,上面的汤姆是非常正确的。