假设我有一个Active Record
类。
如果我有:
房子,有很多人,有很多狗,有很多项圈。
我不会做模式定义,因为它们很简单。
现在我想从一个我有房屋对象的页面来遍历那所房子里的所有项圈。
所以:
for c in house.people.dogs.collars do
puts c
end
如果家中没有人,那么当链转到undefined method
时,我会收到people.dogs
错误。
我可以通过两种方式解决这个问题。我可以将整个事物包含在if语句的嵌套中,一次检查一个级别,如果我首先验证了链的所有部分,则只执行上面的代码。我也可以使用begin
和rescue
。
我的问题是:
还有其他办法吗?一些方法可以让我做一些像:
for c in foo(house.people.dogs.collars) do
puts c
end
没有其他代码。 Foo会检查链是否有效,然后执行它,否则它会默默地做什么。如果没有现成的最佳方法,我将自己创建一个函数并让它返回一个哈希或数组作为保证。
答案 0 :(得分:2)
您的假设不正确。因为house.people
会返回一个数组。而且你无法在该阵列上调用dogs
。您必须为阵列中的每个人拨打dogs
。
以下情况适用于这两种情况,如果协会中有元素或者没有:
house.people.flat_map(&:dogs).flat_map(&:collars)
您可能希望使用has_many through associations清除此问题,或者在house
上使用封装该逻辑的方法。
此外值得一提的是,您将遇到可怕的性能,因为链中的每个步骤都会导致对数据库的多次调用。根据数据库的大小,我会考虑使用数据库连接编写专门的范围。