Reputation: 2501
I would like a clean way in .html.erb to loop through a variable ONLY if the variable is not nil.
I would like the following to execute but not if @family is nil.
<% @family.children.each.with_index(1) do |family_member, index| %>
// HTML HERE
<% end %>
I am trying to avoid doing something like this
<% if @family %>
<% @family.children.each.with_index(1) do |family_member, index| %>
// HTML HERE
<% end %>
<% end %>
And especially trying to avoid needing
<% if @family && @family.children %>
<% @family.children.each.with_index(1) do |family_member, index| %>
// HTML HERE
<% end %>
<% end %>
Is there a better way to do this?
Upvotes: 5
Views: 4807
Reputation: 54882
This solution can be misleading but Ruby's syntax allows you to do so:
<% @family.children.each.with_index(1) do |family_member, index| %>
// HTML HERE
<% end unless @family.blank? %>
# ^^^^^^^^^^^^^^^^^^^^^
I only use this solution for simple statements like testing the presence of an object (like in your case). I do not recommend this solution for a more complex logic because a third party would not know that the condition is at the end of the block.
Another one:
<% (@family.try(:children) || []).each.with_index(1) do |family_member, index| %>
# mu-is-too-short's (brilliant) suggestion:
<% @family.try(:children).to_a.each.with_index(1) do |family_member, index| %>
If @family
is nil
, the try(:children)
won't raise an error but will return nil
, then nil || []
returns the empty array which "you can loop on it" (loop on it zero times actually).
Upvotes: 6
Reputation: 114178
You could use a Null Object, something like:
class NullFamily
def children
[]
end
end
In your controller:
@family = some_finder || NullFamily.new
Or you could pass a separate variable @children
:
@family = some_finder
@children = @family.try(:children).to_a
And change your loop to:
<% @children.each.with_index(1) do |family_member, index| %>
// HTML HERE
<% end %>
Upvotes: 5
Reputation: 310
Maybe you can have this in your controller?
@family ||= []
Upvotes: 1
Reputation: 5144
You can use if @family.present? or the opposite as unless @family.blank?
Upvotes: 0
Reputation: 921
How about this:
<% @family && @family.children.each.with_index(1) do |family_member, index| %>
// HTML HERE
<% end %>
Upvotes: 4