How to refactor this complicated html generator in Ruby? ['content', 'answers', 'comments'].each do |t|
  break if results.length &gt;= MAX_RESULTS
  Question.search_tank('', :conditions =&gt; conditions.merge(t =&gt; "#{search_term}"), :page =&gt; 1, :per_page =&gt; 5).each do |q|
    next if matched_qs.include? q.id
    matched_qs &lt;&lt; q.id

    r = {:title =&gt; q.content, :value =&gt; app_question_url(q.app, q.id)}
    if t == 'content'
      r[:label] = highlight_matched(search_regex, q.content)
      r[:label] &lt;&lt; "&lt;span class='search-type'&gt;Question&lt;/span&gt;"
    else
      r[:label] = q.content
    end

    if t == 'answers'
      r[:label] = "&lt;span class='search-type snippet'&gt;Answer&lt;/span&gt;" + [r[:label], get_snippet(search_regex, q.answers)].compact.join('&lt;br /&gt;')
    end

    if t == 'comments'
      r[:label] = "&lt;span class='search-type snippet'&gt;Comment&lt;/span&gt;" + [r[:type], r[:label], get_snippet(search_regex, q.answers.map(&amp;:comments).flatten)].compact.join('&lt;br /&gt;')
    end

    results &lt;&lt; r
    break if results.length &gt;= MAX_RESULTS
  end


I would like to refactor that part which generates r[:label]
This needs some tweaking, but I hope it helps you identify the main issues to address in your code (IMHO):

objects = [:content, :answers, :comments].flat_map do |type|
  questions = Question.search_tank('', {
    :page =&gt; 1, 
    :per_page =&gt; 5,
    :conditions =&gt; conditions.merge(type =&gt; search_term), 
  })
  questions.map { |q| [q, type] }
end.uniq_by(&amp;:first).take(MAX_RESULTS)

results = objects.map do |q, type| 
  label = case type
  when :content
    highlight_matched(search_regex, q.content) + 
      content_tag(:span, "Question", :class =&gt; "search-type")
  when :answers
    content_tag(:span, "Answer", :class =&gt; 'search-type snippet'&gt;) + 
      [q.content, get_snippet(search_regex, q.answers)].compact.join(tag(:br))
  when :comments
    comments = get_snippet(search_regex, q.answers.flat_map(&amp;:comments))]    
    content_tag(:span, "Comment", :class =&gt; 'search-type snippet'&gt;) +
      [t, q.content, comments].compact.join(tag(:br))
  end
  {:title =&gt; q.content, :value =&gt; app_question_url(q.app, q.id), :label =&gt; label}
end


Notes:


Avoid stateful variables whenever possible (that's it, don't update inplace), work with expressions. 
Use Rails helpers (content_tag, tag, ...).
Use symbols for key-like values, not strings.
"#{something}" -> something.to_s
map + flatten = flat_map. Even though you should able to write q.answer_commments in Rails 3.1 will the correct model settings.
Use case, not a chain of if/elsif if the condition is on the same value.