优雅的处理方式;未定义的方法'each';对于nil:NilClass“;Ruby中的可选关联?

优雅的处理方式;未定义的方法'each';对于nil:NilClass“;Ruby中的可选关联?,ruby,associations,try-catch,optional,Ruby,Associations,Try Catch,Optional,我有一个场景,其中我有可选的关联。有时,协会存在,但有时却不存在 当我试图在屏幕上显示数据时,我遇到了一个问题(想想一个简单的索引操作) 考虑以下应用程序设置: 该项目有许多可交付成果 项目有许多部署记录(此模型的两个属性是'name'和'description') 我对从可交付成果索引操作中提取部署记录关联感兴趣 我让它与以下代码一起工作,但我发现它有点难看: @array = deliverable.try(:project).try(:deployment_record) if @ar

我有一个场景,其中我有可选的关联。有时,协会存在,但有时却不存在

当我试图在屏幕上显示数据时,我遇到了一个问题(想想一个简单的索引操作)

考虑以下应用程序设置:

  • 该项目有许多可交付成果
  • 项目有许多部署记录(此模型的两个属性是'name'和'description')
我对从可交付成果索引操作中提取部署记录关联感兴趣

我让它与以下代码一起工作,但我发现它有点难看:

@array = deliverable.try(:project).try(:deployment_record)
if @array
   @array.each do |r|
   [r.name, r.description].join(' - ')
end
有什么更优雅的方式来重写这个?我试过了

deliverable.try(:project).try(:deployment_record).each do |r|
   [r.name, r.description].join(' - ')
end
但是我一直遇到nil:NilClass的未定义方法'each'错误。我似乎找不到一种方法来优雅地绕过.Nil对象上调用的每个对象。我有一种感觉,不知何故,我应该能够更优雅地做这件事,但我不能把我的手指放在上面


我在代码库中多次重复使用这个截取的代码,所以如果我只是到处复制和粘贴它,那么额外的两行代码真的要了我的命。我很高兴关联检索失败,我只想优雅地失败,没有任何错误或消息。有什么想法吗?

在可交付成果中,
有很多:部署记录,通过::project
然后当您请求部署记录时,它们将作为空集合返回。

您可以使用
to a
方法来确保您有一个要使用的数组(
nil
将生成一个空数组):


这不是最优雅的事情-你必须记住将
添加到a
到你的循环中-但是如果你不能保证
@array
是一个有效的可枚举项,这是防止代码崩溃的最简单的方法。

有点粗俗,但是有
(@array | |[])。每个{…}
选项,或
@array.to_a.each
。不幸的是,我认为让代码真正漂亮的唯一方法就是使用monkey patch
NilClass
,而这类事情通常是不被接受的……谢谢@XavierHolt。一个选项可能与我所希望的最接近。这四个角色可以让我摆脱丑陋的解决方案。我会等着看是否有其他人有更好的建议,如果没有,在24小时内将你的评论作为答案发布,我会接受:)就可以了。不过,我还是希望有人能给出更好的答案——我知道这是我经常忘记键入的四个额外字符@XavierHolt因为你的回答对我帮助最大-你介意把它作为一个帖子贴出来,这样我就可以接受了吗?干杯,你走吧(完全忘了按我说的那样做…)。干杯谢谢@Joshua Check。我试着简化我的问题,这样更容易联系起来,并具有更广泛的通用吸引力。我试图把你的答案融入到我的实际场景中,但没有用。对不起,继续我意外提交的评论:在我的实际问题中,我有4个模型:“类组件属于:可交付成果”“类可交付成果属于:项目”“类项目有很多:可交付成果有很多:部署记录”“类部署记录属于:项目”现在,如果我在组件记录中进行迭代-如何设置以下关联以使其工作?“component.deliverable.project.deployment|u record.each do | dr |'换句话说,我删除了3个关联-有没有办法设置“嵌套”:通过关联?哦,还有最后一条评论。当我打那个电话,但项目模型关联尚未设置时,会发生什么?我一直在运行“项目加载(0.1ms)选择“项目”。*从“项目”中选择“项目”。“id”=0 LIMIT 1 NoMethodError:nil:NilClass的未定义方法“deployment_record”,除非我使用Xavier的工作方法将所有内容转换为数组。
@array.to_a.each do |item|
    #Whatever...
end