如何优雅地检查对象和关联对象的存在?

时间:2019-01-28 02:01:49

标签: ruby-on-rails ruby ruby-on-rails-3.2

我有一个实例变量@tally_property,如果该对象上有photos,我想循环浏览照片并显示它们。

所以我的代码段如下所示:

<% if @tally_property.photos.present? %>
   <% @tally_property.photos.each_with_index do |photo, index| %>

问题是基于上述情况,如果@tally_property为nil,则整个第一行都会引发错误。

所以我可以做一个“零”检查吗,它不笨重,也就是说,我不想在主要对象和关联上都做if @tally_property.nil?,并且优雅,红宝石和护栏-esque?

4 个答案:

答案 0 :(得分:3)

我将使用安全导航操作符(&.)并编写如下内容:

<% @tally_property&.photos&.each_with_index do |photo, index| %>
  ... 
<% end %>

答案 1 :(得分:2)

在Ruby 2.3.0+中,您可以使用安全的导航操作符:

@tally_property&.photos

ActiveSupport具有.try方法,该方法可以在旧版本的ruby中用于同一目的:

@tally_property.try(:photos)

您可以添加一个简单的条件,以能够安全地遍历集合:

<% (@tally_property.try(:photos)||[]).each_with_index do |photo, index| %>

<% end %>

Rails 4添加了ActiveRecord::Relation#none并改变了行为,因此关联始终返回ActiveRecord::Relation。因此写起来完全可以接受:

<% @tally_property.try(:photos).try(:each_with_index) do |photo, index| %>

<% end %>

升级您的应用程序后。或者,您可以使用部分渲染:

<%= render partial: 'photos', collection: @tally_property.photos if @tally_property %>

不需要编写迭代。

答案 2 :(得分:0)

使用&&(或and,它们各有各的优点)。

从Erb中取出一会儿,我通常会这样写:

if @tally_property and @tally_property.photos.present?

我可能会使用photos

if @tally_property and @tally_property.photos

或者也许:

if @tally_property and not @tally_property.photos.empty?

有时我会使用一个临时变量:

if (photos = @tally_property && @tally_property.photos)
  photos.each #…

这种事情。

我会推荐Ruby Tapas的这一集And/Or,以便对它有更长的了解(但仍然很快)。

答案 3 :(得分:-1)

另一种方法,只需选择与此tally_property相关的所有照片:

示例可能如何:

Photo.joins(:tally_property).each_with_index做|照片,索引|