views:

182

answers:

3

I have something like:

<%= @votes %>

With just outputs a string like:

123

Is there a simple way to wrap each character with some html with a helper?

<span class="outerclass">
  <span class="innerclass">
  1
  </span>
</span>

<span class="outerclass">
  <span class="innerclass">
  2
  </span>
</span>

<span class="outerclass">
  <span class="innerclass">
  3
  </span>
</span>
+1  A: 
# View
<%= char_classes(@votes) %>

# Helper
def char_classes(string)
  string.split.map { |char| '<span class="outerclass"><span class="innerclass">' + char + '</span></span>'}.join
end

You'll probably want to choose more expressive method/var names...

floyd
A: 

You could create a helper similar to this:

def wrap_each_char(string, &block)
  string.each_char.map(&block).join
end

Then use it like this (erb):

<%- @votes = "123" -%>
<%- wrap_each_char(@votes) do |c| -%>
  <span class="outer"><span class="inner"><%= c %></span></span>
<%- end -%>

Update: The above example represents one way to pass block level content to a helper, but it's worth noting that this particular example can be simplified by just using the each_char method on the string and avoiding the helper altogether:

<%- @votes.each_char do |c| -%>
  <span class="outer"><span class="inner"><%= c %></span></span>
<%- end -%>
Ryan McGeary
If you're going to put all that in the view, why not just each? (Which is in fact, exactly what I would actually do, but he asked for a helper)
floyd
Agreed, just using `each_char` in the view is more straight forward for the example given in the question, but I suspect he was looking more for an approach to a more general problem. I read into the question such that he was looking for how to pass content from a block into a helper.
Ryan McGeary
hmm.... this worked but it ended out being a little messier as I started adding more, so using the `content_tag` as a block turned out to be a little nicer. Plus Eric is new, so he needs some points.
Joseph Silvashy
+2  A: 

view:

<% @votes.split('').each do |v| %>
  <%= print_vote(v) %>
<% end %>

helper:

def print_vote(vote)
  content_tag(:span, :class => 'outerclass') do
    content_tag(:span, vote, :class => 'innerclass')
  end
end

I'd work toward array'ing the votes before they hit the view, but you're going to have to iterate somewhere and the split doesn't really add much to the implementation anyway. I guess if you really wanted to stuff everything in the helper you could do something like

view:

<%= print_votes(@votes) %>

helper:

def print_votes(votes)
  votes.split('').each do |vote|
    content_tag(:span, :class => 'outerclass') do
      content_tag(:span, vote, :class => 'innerclass')
    end
  end
end

Pretty much the same, it just depends on where you want to put your lines.

Eric Hill
i like this one the most, oddly enough it doesn't actually output the tags, give it a try, perhaps I'm dong it wrong.
Joseph Silvashy
I just edited to add a missing `%>` in the view chunk, so make sure you have that. I've just checked TFM and I think my content_tag nesting is unsupported, so I've changed it to use a block instead.
Eric Hill
oops, I had also forgotten the `.split` in the second helper method.
Eric Hill
I think that the split fixed it.
Joseph Silvashy