Ruby on rails 从Ruby中的哈希数组生成HTML表

Ruby on rails 从Ruby中的哈希数组生成HTML表,ruby-on-rails,ruby,html-table,Ruby On Rails,Ruby,Html Table,从散列数组生成HTML表的最佳方法是什么(理想情况下是一个gem,但必要时是一个代码段) 例如,此哈希数组: [{"col1"=>"v1", "col2"=>"v2"}, {"col1"=>"v3", "col2"=>"v4"}] 应生成此表: <table> <tr><th>col1</th><th>col2</th></tr> <tr><td>v1&l

从散列数组生成HTML表的最佳方法是什么(理想情况下是一个gem,但必要时是一个代码段)

例如,此哈希数组:

[{"col1"=>"v1", "col2"=>"v2"}, {"col1"=>"v3", "col2"=>"v4"}]
应生成此表:

<table>
  <tr><th>col1</th><th>col2</th></tr>
  <tr><td>v1</td><td>v2</td></tr>
  <tr><td>v3</td><td>v4</td></tr>
</table>

冷水
v1v2
v3v4

手工操作似乎并不特别困难。根据您将要使用它的位置,它可能会有自己的方法,但下面是我刚刚编写的小脚本:

表.rb

class Array 
  def to_cells(tag)
    self.map { |c| "<#{tag}>#{c}</#{tag}>" }.join
  end
end

rows = [{"col1"=>"v1", "col2"=>"v2"}, {"col1"=>"v3", "col2"=>"v4"}]
headers = "<tr>#{rows[0].keys.to_cells('th')}</tr>"
cells = rows.map do |row|
  "<tr>#{row.values.to_cells('td')}</tr>"
end.join("\n  ")
table = "<table>
  #{headers}
  #{cells}
</table>"
puts table
类数组
def至_单元(标签)
self.map{c}“{c}}.join
结束
结束
行=[{“col1”=>“v1”,“col2”=>“v2”},{“col1”=>“v3”,“col2”=>“v4”}]
headers=“#{rows[0].keys.to_单元格('th')}”
单元格=行。映射do |行|
“#{row.values.to_单元格('td')}”
结束。加入(“\n”)
表=”
#{headers}
#{cells}
"
摆桌子
输出:

<table>
  <tr><th>col1</th><th>col2</th></tr>
  <tr><td>v1</td><td>v2</td></tr>
  <tr><td>v3</td><td>v4</td></tr>
</table>

冷水
v1v2
v3v4
显然,存在一些问题——首先,它假设第一行的标题与所有其他标题相同。不过,通过在所有未正确分配的标题的所有行中填写nils,您可以非常轻松地预处理和解决此问题

没有gem的原因是生成一个表并不是一项巨大的任务。当你全力以赴,亲自编写代码时,你能做的事情真是太神奇了:)

你可以使用:

需要“生成器”
a=[{“col1”=>“v1”,“col2”=>“v2”},{“col1”=>“v3”,“col2”=>“v4”}]
builder=builder::XmlMarkup.new
columns=a.first.keys
builder.table do|t|
t、 tr do | tr|
列。每个do |列|
tr.th(col)
结束
结束
a、 每行|
t、 tr do | tr|
列。每个do |列|
tr.td(行[列])
结束
结束
结束
结束
p.target
#=>“col1col2v1v2v3v4”

为此使用XMLBuilder:

data = [{"col1"=>"v1", "col2"=>"v2"}, {"col1"=>"v3", "col2"=>"v4"}]
xm = Builder::XmlMarkup.new(:indent => 2)
xm.table {
  xm.tr { data[0].keys.each { |key| xm.th(key)}}
  data.each { |row| xm.tr { row.values.each { |value| xm.td(value)}}}
}
puts "#{xm}"
输出

<table>
  <tr>
    <th>col1</th>
    <th>col2</th>
  </tr>
  <tr>
    <td>v1</td>
    <td>v2</td>
  </tr>
  <tr>
    <td>v3</td>
    <td>v4</td>
  </tr>
</table>

可乐
可乐
v1
v2
v3
v4

Matchu的回答给了我很多启发,我将其修改为自定义方法,而不是更改内置类(除非有很好的理由,否则不要这样做)

除了生成表之外,数组的结构可能更方便、更直观地访问元素

让整个表存储在二维数组中,例如

@table_array = [
                 ["Name","Gender","Age"],
                 ["Andy","M","20"],
                 ["Mary","F","19"],
                 ["Tony","M","18"]
              ]
其中第一个元素作为表头,其余元素作为表内容。现在,我们可以使用格式良好的table_数组和table class属性生成一个table html代码:

def ToCell (tag,value)
    value.map{ |c| "<#{tag}>#{c}</#{tag}>" }.join   
end

def ToTable (table_array, table_class)
    headers = "<tr>" + ToCell('th',table_array[0]) + "</tr>"
    cells = table_array[1..table_array.count].map{ |each_row|
        "<tr>#{ToCell('td',each_row)}</tr>"             
    }.join

    table = "<table class=\"#{table_class}\"><thead>#{headers}</thead><tbody>#{cells}</tbody></table>"
end
def ToCell(标签、值)
value.map{c}“{c}}.join
结束
def ToTable(表格数组、表格类)
headers=“”+ToCell('th',表_数组[0])+“”
cells=table_array[1..table_array.count].map{124;每行|
#{ToCell('td',每行)}
}.加入
table=“#{headers}#{cells}”
结束
并将其嵌入到.erb文件中

<%= ToTable(@table_array,"table").html_safe %>

如果您从浏览器中看到,输出将是这样的

<table class="table">
     <thead>
            <tr><th>Name</th><th>Gender</th><th>Age</th></tr>
     </thead>
     <tbody>
            <tr><td>Andy</td><td>M</td><td>20</td></tr>
            <tr><td>Mary</td><td>F</td><td>19</td></tr>
            <tr><td>Tony</td><td>M</td><td>18</td></tr>
     </tbody>
</table>

姓名性别
AndyM20
玛丽19
TonyM18
我开发的gem具有您想要做的功能。您可以在Ruby代码中轻松创建这样的表:

require "dom"
[%w[aaa bbb], %w[ccc ddd]].dom(:td, :tr, :table)
# => "<table><tr><td>aaa</td><td>bbb</td></tr><tr><td>ccc</td><td>ddd</td></tr></table>"
需要“dom”
[%w[aaa bbb],%w[ccc ddd]].dom(:td,:tr,:table)
#=>“aaabbbccddd”

我刚刚注意到,由于我最终更改了脚本,所以输出肯定不是这样。只需几秒钟就可以编辑。我们同时发布了相同的解决方案:-)这个答案被低估了。这个示例脚本提供了Ruby和builder当前版本的线索,并提供了以下输出:$Ruby test.rb col1 col2 v1 v3 v4用下面是它的工作原理:放置“#{xm.target!}”
# modified from Harish's answer, to take care of sparse hashes:

require 'builder'

def hasharray_to_html( hashArray )
  # collect all hash keys, even if they don't appear in each hash:
  headers = hashArray.inject([]){|a,x| a |= x.keys ; a}  # use array union to find all unique headers/keys                              

  html = Builder::XmlMarkup.new(:indent => 2)
  html.table {
    html.tr { headers.each{|h| html.th(h)} }
    hashArray.each do |row|
      html.tr { row.values.each { |value| html.td(value) }}
    end
  }
  return html
end
require "dom"
[%w[aaa bbb], %w[ccc ddd]].dom(:td, :tr, :table)
# => "<table><tr><td>aaa</td><td>bbb</td></tr><tr><td>ccc</td><td>ddd</td></tr></table>"