Rails helper方法:嵌套哈希到嵌套HTML列表

时间:2013-02-15 22:57:29

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-3.2

我正在尝试编写一个Rails帮助器方法,将嵌套的哈希转换为嵌套的HTML列表。

例如:

{
  :parent => "foo",
  :children => [
    {
      :parent => "bar",
      :children => [
        {
          :parent => "baz",
          :children => []
        }
      ]
    }
  ]
}

应该成为:

<ul>
  <li>foo</li>
  <ul>
    <li>bar</li>
    <ul>
      <li>baz</li>
    </ul>
  </ul>
</ul>

散列可以包含任意数量的级别,以及每个级别的任意数量的父级。

最好的方法是什么?

2 个答案:

答案 0 :(得分:5)

您可以使用递归方法渲染以散列到嵌套的列表集。将其放在您的相关助手中:

def hash_list_tag(hash)
  html = content_tag(:ul) {
    ul_contents = ""
    ul_contents << content_tag(:li, hash[:parent])
    hash[:children].each do |child|
      ul_contents << hash_list_tag(child)
    end

    ul_contents.html_safe
  }.html_safe
end

答案 1 :(得分:1)

Zach Kemp的回答非常有效地解决了这个问题。如果你正在寻找一些更通用的东西(一个你不知道密钥名称的嵌套哈希),就像我一样,以下模块可能会有所帮助(同样在https://github.com/sjohnson/auto_hash_display有更多细节):

module HashFormatHelper
  # These methods add classes to the HTML structure that are defined in Bootstrap (and can be defined for other CSS frameworks)
  def format_hash(hash, html = '')
    hash.each do |key, value|
      next if value.blank?
      if value.is_a?(String) || value.is_a?(Numeric)
        html += content_tag(:ul, class: 'list-group') {
          ul_contents = ''
          ul_contents << content_tag(:li, content_tag(:h3, key.to_s.underscore.humanize.titleize), class: 'list-group-item')
          ul_contents << content_tag(:li, value, class: 'list-group-item')

          ul_contents.html_safe
        }
      elsif value.is_a?(Hash)
        html += content_tag(:ul, class: 'list-group') {
          ul_contents = ''
          ul_contents << content_tag(:li, content_tag(:h3, key.to_s.underscore.humanize.titleize), class: 'list-group-item')
          inner = content_tag(:li, format_hash(value), class: 'list-group-item')
          ul_contents << inner

          ul_contents.html_safe
        }
      elsif value.is_a?(Array)
        html += format_array(value)
      else
        Rails.logger.info "Unexpected value in format_hash: #{value.inspect}"
        Rails.logger.info "value type: #{value.class.name}"
      end
    end
    html.html_safe
  end

  def format_array(array, html = '')
    array.each do |value|
      if value.is_a?(String)
        html += content_tag(:div, value).html_safe
      elsif value.is_a?(Hash)
        html += format_hash(value)
      elsif value.is_a?(Array)
        html += format_array(value)
      else
        Rails.logger.info "Unexpected value in format_array: #{value.inspect}"
        Rails.logger.info "value type: #{value.class.name}"
      end
    end
    html
  end
end

此代码也可用于通过将哈希值设置为等于Hash.from_xml(your_xml_data)然后将其传递给format_hash(哈希)来显示XML。

请注意,from_xml方法可能会剥离XML标记属性,因此最适合没有属性的XML。