Каков лучший способ (идеально драгоценный камень, но фрагмент кода при необходимости) для генерации 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>
Используйте для этого 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>
Это не кажется особенно сложным для выполнения вручную. В зависимости от того, где вы собираетесь его использовать, это, вероятно, следует поместить в отдельный метод, но вот небольшой сценарий, который я только что написал:
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
Output:
<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 во всех строках для всех заголовков, не присвоенных должным образом.
Причина, по которой не существует драгоценного камня, заключается в том, что создание таблицы на самом деле не является огромной задачей. Удивительно, что вы можете сделать, если пристегнетесь и действительно напишете что-то самостоятельно :)
Вы можете использовать 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/>"