content_tag concatenation clean up I need to concatenate two content_tag and it works but it seems a little messy to me. Any thoughts on how may I refactor this?

def format_price(money)
  mny = get_price_string(money).to_money
  str = content_tag(:span, @visitor.currency.symbol.html_safe, class: 'pounds')
  str &lt;&lt; mny.format(no_cents: true, symbol: '')
  str &lt;&lt; content_tag(:span, mny.format[-3, 3], class: 'pence') unless condition?
end
Notes:


Before refactoring, let's identify what makes this code feel "messy". IMO there are two problems: the in-place method &lt;&lt; and the inline statement unless. As usual, I'll try to make the case for functional programming (as opposed to imperative programming, not opposed to OOP). I guess you are not familiar with FP in Ruby but somehow you felt something was wrong. A quick intro: when you update variables in-place, the = symbol loses a lot of its glamour :-) In maths x = "hello" means that, in this scope, x is always equal to 'hello'. Period. In imperative programming it means "for now x is equal to 'hello', but I reserve the right to change it whenever I feel like it, in this scope or any other. Good luck debugging!". I don't know about you, but I prefer = to mean the first one :-) Yes, even for a such simple and short code.
I don't understand: m.format, where is m? is it mny?
ebeach?. What is ebeach??
m.format[-3, 3]. Do you want the last 3 chars of a string? In Rails: m.last(3).
@visitor: Using an instance variable in a helper is a no-no. Pass it as an argument.


So let's rewrite the snippet in functional style. There are at least two ways, 1) use different variable names for the different values and concat the strings, or 2) use an array+compact+join. The first:

def format_price(money_value, visitor)
  money = get_price_string(money_value).to_money
  symbol = content_tag(:span, visitor.currency.symbol.html_safe, class: 'pounds')
  value = money.format(no_cents: true, symbol: '')
  currency = ebeach? ? "" : content_tag(:span, money.format.last(3), class: 'pence')
  symbol + value + currency
end


Note how pure functions in FP follow a simple pattern: create intermediate variables (if needed, to make the method more readable and declarative) and use them in the last expression of the method. Don't "do things", declare "what things are".

Second approach:

def format_price(money_value, visitor)
  money = get_price_string(money_value).to_money
  [
    content_tag(:span, visitor.currency.symbol.html_safe, class: 'pounds'),
    money.format(no_cents: true, symbol: ''),
    *(content_tag(:span, money.format.last(3), class: 'pence') if condition?),
  ].join
end


Of course an alternative approach would have been to create a partial view instead of rendering from a helper.