简体   繁体   中英

How do I elegantly check for presence of both the object and associated objects?

I have an instance variable @tally_property , and if there are photos on that object I would like to cycle through the photos and show them.

So my code snippet looks like this:

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

The issue is that based on the above, if @tally_property is nil, then the entire first line throws an error.

So is there a 'nil' check I can do that isn't bulky, ie I don't want to do if @tally_property.nil? , on both the primary object and the association, and is elegant and ruby & rails-esque?

I would use the safe navigation operator ( &. ) and write something like this:

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

In Ruby 2.3.0+ you can use the safe navigation operator:

@tally_property&.photos

ActiveSupport has a .try method that can be used to the same end in older versions of ruby:

@tally_property.try(:photos)

You can add a simple conditional to be able to safely iterate through the collection:

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

<% end %>

Rails 4 adds ActiveRecord::Relation#none and a change in behaviour so that associations always return a ActiveRecord::Relation . So its perfectly acceptable to write:

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

<% end %>

After upgrading your app. Or you can use a partial and render:

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

Which removes the need for writing the iteration.

Use && (or and , they each have their sweetspot).

Taking it out of Erb for a moment, I would generally write something like this:

if @tally_property and @tally_property.photos.present?

Depending on photos I might use:

if @tally_property and @tally_property.photos

or perhaps:

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

Sometimes I'll use a temporary variable:

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

That kind of thing.

I would recommend this episode of Ruby Tapas, And/Or for a longer (but still quick) look at it.

One more way, just select all photos connected to this tally_property:

example how it might be:

Photo.joins(:tally_property).each_with_index do |photo, index|

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM