Dynamic display of an array of hashes in a html ta

2019-02-24 19:29发布

问题:

I have a database called "products" that has a field that uses hstore called data.

At the moment, in my index.html.haml, I'm just looping through products and displaying their data as a hash:

- @products.each do |product|
  =product.data #THIS PRINTS A HASH
  %hr

Which, for example, could print a hash like:

{"Name"=>"Example","type"=>"book", "price"=>"7.99"}

I'd like to make a HTML table that could hold a dynamic number of keys and values, and print them into columns with values corresponding to keys. Here's a diagram:

Thanks for all help!

回答1:

Hope this can help:

Solution 1: based on same .data content # Deprecated

Conditions:

  • All product.data have the same amount of pairs of key/value.
  • The order of the pairs is the same for all the products.

The code:

# headers
%tr
  - @products.first.data.keys.each do |attribute_name|
    %th= attribute_name
# body
- @products.each do |product|
  %tr
    - product.data.attributes.each do |attribute_value|
      %td= attribute_value

This code will render properly if each product.data has the same amount of key/value pairs AND stored in the same order.


Solution 2: fully dynamic (.data varying) # Recommended

Conditions:

  • The number of pairs (of key/val) of product.data is varying between each product
  • The order of the pairs is not the same for all the products.

The code:

# we gather all possible attribute's name in the data hash:
- headers = @products.map(&:data).flat_map(&:keys).uniq

%tr 
  # we make a table-head cell for each attribute's name:
  - headers.each do |key|
    %th= key

- @products.each do |product|
  %tr # for each attribute's name, we display a TD cell and try to display it's value if exists
    - headers.each do |key|
      %td= product.data[key]

Feel free to ask for details, I feel like I just gave you a piece of code without any explanation...