2011-01-19 70 views
5

我有很多模特和关系。由于这个事实,有很多的意见/控制器调用,这看起来是这样的:在Rails/Ruby中检查对象是否存在的正确方法是什么?

@object.something.with_something.value 

链可以最终被零,这是完全正常的某些部分。检查终端对象是否存在的适当/清洁/快速的方法是什么?

在呼唤这样的:

@object.something.with_something.value if defined? @object.something.with_something.value 

考虑行?

+0

这个问题其实并不是很清楚......你只关心`@ object.something.with_something.value`是`nil`还是你担心`NoMethodError`会引起如果链是'无'?我假设后者? – 2011-01-19 22:27:35

回答

8

从本质上说,您需要使用&&运算符(而不是defined?),但这可能非常快速地变得非常冗长。的

所以不是这样:

(@object && @object.something && @object.something.with_something && 
    @object.something.with_something.value) 

你可以做到这一点时的ActiveSupport存在:

@object.try(:something).try(:with_something).try(:value) 

或安装invocation construction kit并使用其把守的评估工具:

Ick::Maybe.belongs_to YourClass 
maybe(@object) { |obj| obj.something.with_something.value } 
2

what.you.are.doing有时被称为“列车残骸”。它也被描述为违反德米特法。

这就是说,我认为有一种叫做“andand”的东西可以帮助你做什么。

+1

是的,`对象#andand`是一个解决方案,但我尽量避免它 - 引入一个依赖关系有点奇怪,这实际上给了你一种方法。另外,它默认情况下会修改Object类,这很糟糕。 – 2011-01-19 22:17:43

3

最好安排其余的代码以便最多查看此问题链中的最后一个对象。

defined?不会做你想要的。东西可以是defined?nil在同一时间。

当问题被引用链限制在最后一个属性:

@object.something.with_something.value if @object.something.with_something 

我可能采取的事实的优点:

nil.to_a => [] 
nil.to_s => '' 
nil.to_f => 0.0 
nil.to_i => 0 

所以,如果你知道什么是或者nilArray,通常你可以编写更好的代码而没有任何条件根本就是写下类似的东西:

something.to_a.each do |e| 
    . . . 
+0

是的,我重读OP并找出你的意思。我仔细阅读了OP的问题,因为我知道我回答的问题更可能是他实际遇到的麻烦。 – 2011-01-19 22:38:49

+2

说实话,我并不是你的解决方案的忠实粉丝。我已经看到它出现了几次,并且每当我看到它时就删除它,因为我非常强烈地感觉到它使得代码不易读。其他方法,如`try`和`maybe`可以更普遍地解决问题,并以更可读的方式进行。 – 2011-01-19 22:41:47

0

另一种选择是使用Null Object pattern来确保这些对象都不为零。可以说,如果你的代码要以这种方式链接,那么应该总是定义

相关问题