从Ruby中的哈希数组生成HTML表
什么是从散列数组生成HTML表格的最佳方法(理想情况下是gem,但必要时还有代码片段)?
例如,这个哈希数组:
[{"col1"=>"v1", "col2"=>"v2"}, {"col1"=>"v3", "col2"=>"v4"}]
应该生成这个表:
col1 col2 v1 v2 v3 v4
使用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}"
产量
col1 col2 v1 v2 v3 v4
# 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
这似乎并不特别难以手工完成。 根据你将要使用它的位置,这可能应该在某个地方使用自己的方法,但这里是我刚写的小脚本:
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 = "#{rows[0].keys.to_cells('th')} " cells = rows.map do |row| "#{row.values.to_cells('td')} " end.join("\n ") table = " #{headers} #{cells}
" puts table
输出:
col1 col2 v1 v2 v3 v4
显然,存在一些问题 – 例如,它假设第一行的标题与所有其他标题相同。 但是,您可以非常轻松地预处理和解决此问题,方法是在所有行中填入nils,以便未正确分配所有标题。
没有gem的原因是生成表并不是一项巨大的工作。 当你扣下来并自己编写代码时,你可以做的事情真是太棒了:)
您可以使用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 #=> "col1 col2 v1 v2 v3 v4
"
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 = "" + ToCell('th',table_array[0]) + " " cells = table_array[1..table_array.count].map{ |each_row| "#{ToCell('td',each_row)} " }.join table = "#{headers}#{cells}
" end
并将其嵌入.erb文件中
<%= ToTable(@table_array,"table").html_safe %>
如果从浏览器中看到,输出将是这样的
Name Gender Age Andy M 20 Mary F 19 Tony M 18
我开发的dom gem具有你想要做的function。 您可以在Ruby代码中轻松创建这样的表:
require "dom" [%w[aaa bbb], %w[ccc ddd]].dom(:td, :tr, :table) # => "aaa bbb ccc ddd
"