2010-04-13 84 views
8

从一组哈希中生成HTML表格的最佳方式(理想情况下是gem,但必要时是代码片段)是什么?从Ruby中的哈希阵列生成HTML表格

例如,该阵列散列:

[{"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> 

回答

9

使用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> 
4

这似乎并不特别困难用手做。根据你要去的地方使用它,这也许应该去它自己的方法的地方,但这里的小剧本我只写了:

table.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 

输出:

<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> 

显然,有一些问题 - 首先,它假定该行一个标题的都是一样的,因为所有其他标题。尽管如此,您可以很容易地预处理和解决这个问题,通过在所有行中填写nils来标识未正确分配的所有标题。

没有宝石的原因在于生成表格并不是一项巨大的任务。这是惊人的,当你扣下来,实际上代码自己的东西:)

+0

我只注意到,因为我最终改变剧本,输出是最肯定不是这样。在短短一秒钟内编辑。 – Matchu 2010-04-14 01:20:23

+1

已编辑。好多了。 – Matchu 2010-04-14 01:21:36

4

你可以使用你能做什么builder

require 'builder' 

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| 
    columns.each do |col| 
     tr.th(col) 
    end 
    end 
    a.each do |row| 
    t.tr do |tr| 
     columns.each do |col| 
     tr.td(row[col]) 
     end 
    end 
    end 
end 
p builder.target 
#=> "<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><target/>" 
+0

这就是我们在同一时间发布相同的解决方案:-) – 2010-04-14 06:54:50

1

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

此外,在生成表格时,Array的结构可能更方便,更直观地访问元素。

让存储在2-d阵列整个表,说

@table_array = [ 
       ["Name","Gender","Age"], 
       ["Andy","M","20"], 
       ["Mary","F","19"], 
       ["Tony","M","18"] 
       ] 

,其中每个所述第一元件用作表标题和其余的是表的内容。现在,我们可以使用格式良好的table_array中和表类属性生成表格的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 

,并嵌入它。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> 
10
# 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 
+2

这个答案是如此低估。 – 2014-08-02 10:32:56

+0

让它评价:) – zee 2016-02-08 05:15:51

+0

谢谢你,伙计们! :) – Tilo 2016-02-08 18:34:38

0

,我已经制定了,你想做什么功能的dom宝玉见。您可以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>"