2010-04-13 6 views
8

Was ist der beste Weg (idealerweise ein Juwel, aber ein Code-Snippet, falls erforderlich), um eine HTML-Tabelle aus einem Array von Hashes zu generieren?Generieren Sie eine HTML-Tabelle aus einem Array von Hashes in Ruby

Zum Beispiel dieses Array von Hashes:

[{"col1"=>"v1", "col2"=>"v2"}, {"col1"=>"v3", "col2"=>"v4"}] 

diese Tabelle erzeugen soll:

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

Antwort

9

Verwenden Sie die XMLBuilder hierfür:

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

Ausgabe

<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

Dies gilt nicht besonders schwierig erscheinen, von Hand zu tun. Je nachdem, wo du gehst, es zu benutzen, sollte dies irgendwo in seinem eigenen Verfahren geht wahrscheinlich, aber hier ist das kleine Skript schrieb ich gerade oben:

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 

Ausgang :

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

Offensichtlich gibt es einige Probleme - für einen, es wird davon ausgegangen, dass die Reihe sind einer der Überschriften die gleichen wie alle anderen Rubriken. Sie können das aber recht einfach vorverarbeiten und umgehen, indem Sie in allen Zeilen Nils für alle nicht richtig zugeordneten Überschriften eintragen.

Der Grund, warum es keinen Edelstein gibt, ist, dass das Erzeugen eines Tisches nicht wirklich ein großes Unterfangen ist. Es ist erstaunlich, was Sie tun können, wenn Sie sich dahinter klemmen und tatsächlich Code etwas selbst :)

+0

Ich habe gerade festgestellt, dass, da ich am Ende das Skript geändert wurde, ist die Ausgabe definitiv nicht das. In nur einer Sekunde bearbeiten – Matchu

+1

Bearbeitet. Viel besser. – Matchu

4

können Sie verwenden 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

Das ist uns die gleiche Lösung zur gleichen Zeit :-) –

1

Matchus answe r inspirierte mich sehr und ich modifizierte es zu selbstdefinierten Methoden, anstatt die eingebaute Klasse zu ändern (tun Sie das nicht, außer Sie haben einen wirklich guten Grund).

Darüber hinaus beim Generieren einer Tabelle, Array-Struktur vielleicht viel bequemer und intuitiver Zugriff auf Elemente.

die gesamte Tabelle in einem 2-D-Array gespeichert Lassen, sagen

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

in der jeweils das erste Element dient als der Tabellenkopf und der Rest ist Tabelleninhalt. Nun können wir die gut formatierte table_array verwenden und eine Tabellenklasse Attribut eine Tabelle HTML-Code zu generieren:

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 

und betten sie in.erb

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

der Ausgang so etwas wie dies wäre Datei, wenn u aus dem Browser sieht

<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

Diese Antwort ist so unterbewertet. –

+0

machte es bewertet :) – zee

+0

danke, Jungs! :) – Tilo

0

Das dom Juwel, das ich entwickelt habe, um die Funktionalität von dem, was Sie tun mögen. Sie können eine Tabelle wie diese alle leicht in Ruby-Code erstellen:

Verwandte Themen