处理nil对象和属性的最佳实践是什么?

Dav*_*ers 6 ruby ruby-on-rails

假设我有一个User具有email属性的对象,我需要他们的上一个字母email:

u = User.find(1)    
letter = u.email.upcase.last
Run Code Online (Sandbox Code Playgroud)

如果u或者emailnil在这条产业链,然后我得到一个NoMethodError: undefined method 'blah' for nil:Nilclass.在大多数情况下,我应该能够解决这个问题,但有时候,nil它应该得到它不应该或者很难包含的地方.一种方法是冗长的:

u = User.find(1)
letter = nil
if u && u.email
 letter = u.email.upcase.last
end
Run Code Online (Sandbox Code Playgroud)

但是这在某种观点或长链中会变得烦人和危险a.bunch.of.properties.down.a.hierarchy.我try在Rails中阅读了有关方法的内容:

u = User.find(1)
letter = u.try(:email).try(:upcase).try(:last)
Run Code Online (Sandbox Code Playgroud)

这不那么冗长,但我觉得写这些尝试都很蠢.一旦我放入try链条,我就必须一直使用它们.有没有更好的办法?

car*_*nts 8

我喜欢使用Null对象模式.Avdi有一篇很好的帖子解释了这一点,但基本的想法是你有一个小类可以代表一个对象并合理地回应你可能传递原始对象的消息.我发现这些不仅对于避免NoMethodErrors而且对于设置默认值/好消息也很有用.

例如,你可以这样做:

class NilUser
  def email
    "(no email address)"
  end
end

u = User.find(1) || NilUser.new
u.email.upcase.last # => No errors!
Run Code Online (Sandbox Code Playgroud)

  • 我亲自扩展了这个.我在我的User模型中添加了一个`self.safe_find(id)`方法,其中包含`User.find(id)|| NilUser.new`位.这样我的观点就不那么杂乱,只有'u = User.safe_find(1)`. (2认同)