从哈希数组中生成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>
答案 0 :(得分:12)
# 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
答案 1 :(得分:10)
使用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>
答案 2 :(得分: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,以便所有标题都没有正确分配。
没有宝石的原因是生成表并不是一项巨大的任务。当你扣下并自己编写代码时,你可以做些什么:)
答案 3 :(得分: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/>"
答案 4 :(得分:1)
Matchu的答案给了我很多启发,我将其修改为自定义方法,而不是更改内置类(除非你有一个非常好的理由,否则不要这样做)。
此外,在生成表时,Array的结构可能更方便,更直观地访问元素。
让整个表存储在二维数组中,比如说
@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>
答案 5 :(得分:0)
我开发的dom 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>"