3
\$\begingroup\$

I have an array of hints. Sometimes, this array could contain an empty string. Occasionally, the array might contain only empty strings, in which case I want the whole block to be skipped. This is what I came up with:

<% @hints.each do |hint| %>
    <% unless hint.empty? %>
        <p>Please observe the following hints:</p>

        <ul>
        <% @hints.each do |hint| %>
            <% unless hint.empty? %>
                <li><%= hint %></li>
            <% end %>
        <% end %>
        </ul>

        <% break %>
    <% end %>
<% end %>

An example of @hints:

["", "", "Have you tried turning it off and on again?"]

Or:

[""]

Anyone know a better way?

\$\endgroup\$
2
  • \$\begingroup\$ Is this code working for you? you have two nested @hints.each... \$\endgroup\$
    – tokland
    Commented Oct 30, 2014 at 11:56
  • \$\begingroup\$ @tokland I know right! It was the only thing I could think of. The first @hints.each gets stopped as soon as a non-empty string is detected so in theory the nested @hints.each only gets ran once. Oh, I just noticed how that second unless hint.empty? is not necessary. It works though. \$\endgroup\$
    – Phasy
    Commented Oct 30, 2014 at 12:09

1 Answer 1

2
\$\begingroup\$

As @tokland pointed out, your current code has one too many loops really.

As for checking if all the strings are empty, you have some options.

1) The any? method accepts a block, so you can test if any of the elements in an array match a certain condition. In your case, you could do

@hints.any? { |string| string.present? }

since present? checks if a string is non-empty. But you can also shorten that to just

@hints.any?(&:present)

With that you could do something like

<% if @hints.any?(&:present) %>
    <p>Please observe the following hints:</p>

    <ul>
    <% @hints.each do |hint| %>
        <% unless hint.empty? %>
            <li><%= hint %></li>
        <% end %>
    <% end %>
    </ul>
<% end %>

2) Alternatively, and I'd say nicer, you can filter the array beforehand, to simply not include blank strings using select or, conversely, reject.

@hints = some_hints.reject(&:blank?)   # reject blank strings
# or...
@hints = some_hints.select(&:present?) # keep non-blank strings

This should happen in the controller when you first set @ hints (or even earlier - don't know where the hints come from, but there's little need to keep empty strings around if you don't have to, so either strip them out early, or just avoid adding them to begin with).

With a "clean" @hints array you can do this:

<% unless @hints.empty? %>
    <p>Please observe the following hints:</p>

    <ul>
    <% @hints.each do |hint| %>
        <li><%= hint %></li>
    <% end %>
    </ul>
<% end %>
\$\endgroup\$
2
  • \$\begingroup\$ Thanks! .any?, .reject and .select were all new to me. \$\endgroup\$
    – Phasy
    Commented Oct 30, 2014 at 14:11
  • 3
    \$\begingroup\$ @Phasy Do yourself a favor and read through the documentation for Array and Enumerable. Just read as much as you can stomach. It really some of the most useful stuff in Ruby. Map, reduce/inject, zip, transpose, select, reject, etc. etc.. You'll end up using all of these things a lot. Trust me, it's worth it. \$\endgroup\$
    – Flambino
    Commented Oct 30, 2014 at 14:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.