6

在我的大多数应用程序中,我都有一个current_user方法。为了避免在current_user.namewhere current_useris等情况下出现异常nil,rails 提供了该try方法。这样做的问题是我需要记住在try任何地方current_user都可以使用nil.

我想使用 Null Object 模式来消除这种额外的开销。

class NullUser
  def method_missing(method_name, *args)
    nil
  end
end

def current_user
  return NullUser.new unless UserSession.find
  @current_user ||= UserSession.find.user
end

try这在某些情况下可以替代:

current_user.try(:first_name)     #=> nil
current_user.first_name           #=> nil

但进一步链接失败:

current_user.profiles.first.name    #=> undefined method...

我试图返回空对象:

class NullUser
  def method_missing(method_name, *args)
    self.class.new
  end
end

current_user.try { |u| u.profiles.first.name }  #=> nil
current_user.profiles.first.name                #=> nil

但这在其他情况下会失败:

current_user.is_admin?            #=>  #<NullUser:0x96f4e98>

这个问题有没有可能的解决方案,还是我们都必须忍受try

4

2 回答 2

8

我会坚持使用NullUser但将其名称更改GuestUser为使事情更清楚。此外,您应该从您的 User 类中存根所有重要的方法,例如

class GuestUser
  def method_missing(method_name, *args)
    nil
  end

  def is_admin?
    false
  end

  # maybe even fields:
  def name
    "Guest"
  end

  # ...
end
于 2013-04-18T11:24:36.887 回答
3

如果您希望能够在NullUser实例上链接方法,则需要使用method_missingreturnself而不是nil. 您尝试返回self.class.new很接近...

Avdi Grim 解释了如何在 Ruby 中实现空对象模式。

于 2014-04-23T22:00:11.350 回答