DollarChills
DollarChills

Reputation: 1086

Looping Multiple Arrays by year

I'm looking multiple arrays but having trouble with aligning them in a table based on year. At the moment the data doesn't line up with the corresponding year, if data exists in any year it just places the data at the first row, then places '0' data for the rest, ie. not aligning with the year.

View

<table>
<% @a.zip(@b, @c, @d) do |a, b, c, d| %>
 <tr>
  <td><%= a.year %></td>
  <% if a.blank? %>
    <td>0</td>
    <td>0</td>
  <% else %>
    <td><%= a.id %></td>
    <td><%= a.data %></td>
  <% end %>
  <% if b.blank? %>
    <td>0</td>
    <td>0</td>
  <% else %>
    <td><%= b.id %></td>
    <td><%= b.data %></td>
  <% end %>
  <% if c.blank? %>
    <td>0</td>
    <td>0</td>
  <% else %>
    <td><%= c.id %></td>
    <td><%= c.data %></td>
  <% end %>
  <% if d.blank? %>
    <td>0</td>
    <td>0</td>
  <% else %>
    <td><%= d.id %></td>
    <td><%= d.data %></td>
  <% end %>
 </tr>
</table>

Controller

@a = Result.where(id: params[:id_select]).group('year').where('data > 0').select('AVG(data) AS data, year as year, COUNT(id) AS id').order('year ASC')

@b = Result.where(id: params[:id_select]).group('year').where('data > 0').select('AVG(data) AS data, year as year, COUNT(id) AS id').where('id = ?', '0').order('year ASC')

@c = Result.where(id: params[:id_select]).group('year').where('data > 0').select('AVG(data) AS data, year as year, COUNT(id) AS id').where('id = ?', '1').order('year ASC')

@d = Result.where(id: params[:id_select]).group('year').where('data > 0').select('AVG(data) AS data, year as year, COUNT(id) AS id').where('id = ?', '2').order('year ASC')

Upvotes: 10

Views: 236

Answers (3)

MrYoshiji
MrYoshiji

Reputation: 54882

In the controller:

@results_by_year = Result.where(your_conditions).group_by(&:year)
# this retrieves all the Result records wanted, without taking care of the record's `year`

The hash's structure will be like this:

# { 2010: [<Result id:1>, <Result id:3>], 
#   2012: [<Result id:2>], 
#   2014: [<Result id:7>, <Result id:9>] }

In the view:

@results_by_year.each do |year, results|
  = year
  - results.each do |result|
    = result.id
    = result.data
end

Upvotes: 1

Vishal Jain
Vishal Jain

Reputation: 1940

I think you can try this way. in this you have not need to check for blank values. i hope @a contains all your available years otherwise you needs to merge all years an loop through years

<table>
<% @a.each do |a| %>
 <tr>
  <td><%= a.year %></td>
    <td><%= (a.id || 0 rescue 0) %></td>
    <td><%= (a.data || 0 rescue 0) %></td>
    <td><%= (@b.select{|h| h if h["year"] == a.year }.first.id || 0 rescue 0) %></td>
    <td><%= (@b.select{|h| h if h["year"] == a.year }.first.data || 0 rescue 0 ) %></td>
    <td><%= (@c.select{|h| h if h["year"] == a.year }.first.id || 0 rescue 0) %></td>
    <td><%= (@c.select{|h| h if h["year"] == a.year }.first.data || 0 rescue 0) %></td>
    <td><%= (@d.select{|h| h if h["year"] == a.year }.first.id || 0 rescue 0) %></td>
    <td><%= (@d.select{|h| h if h["year"] == a.year }.first.data || 0 rescue 0) %></td>
 </tr>
<% end %>
</table>

If your @a not contains all years then just try to merge it by

years = ((@a.collect{|h| h["year"]}) + (@b.collect{|h| h["year"]}) + (@c.collect{|h| h["year"]}) + (@d.collect{|h| h["year"]})).uniq

then you can just looping through years array as:

<% years.each do |year| %>
     <tr>
      <td><%= year %></td>
        <td><%= (@a.select{|h| h if h["year"] == year }.first.id || 0 rescue 0) %></td>
        <td><%= (@a.select{|h| h if h["year"] ==  year }.first.data || 0 rescue 0 ) %></td>
        <td><%= (@b.select{|h| h if h["year"] == year }.first.id || 0 rescue 0) %></td>
        <td><%= (@b.select{|h| h if h["year"] ==  year }.first.data || 0 rescue 0 ) %></td>
        <td><%= (@c.select{|h| h if h["year"] == year }.first.id || 0 rescue 0) %></td>
        <td><%= (@c.select{|h| h if h["year"] == year }.first.data || 0 rescue 0) %></td>
        <td><%= (@d.select{|h| h if h["year"] == year }.first.id || 0 rescue 0) %></td>
        <td><%= (@d.select{|h| h if h["year"] == year }.first.data || 0 rescue 0) %></td>
     </tr>
    <% end %>
    </table>

Upvotes: 4

dimakura
dimakura

Reputation: 7655

You probably mean this in your view:

<%
  A = @a.group_by{|a| a.year}
  B = @b.group_by{|b| b.year}
  C = @c.group_by{|c| c.year}
  D = @d.group_by{|d| d.year}
%>

<table>
  <% A.each do |year, a| %>
    <% b = B[year] %>
    <% c = C[year] %>
    <% d = D[year] %>
    <tr>
      <td><%= year %></td>
      <% if a.blank? %>
        <td>0</td>
        <td>0</td>
      <% else %>
        <%= a.id %>
        <%= a.data %>
      <% end %>
      <% if b.blank? %>
        <td>0</td>
        <td>0</td>
      <% else %>
        <td><%= b.id %></td>
        <td><%= b.data %></td>
      <% end %>
      <% if c.blank? %>
        <td>0</td>
        <td>0</td>
      <% else %>
        <td><%= c.id %></td>
        <td><%= c.data %></td>
      <% end %>
      <% if d.blank? %>
        <td>0</td>
        <td>0</td>
      <% else %>
        <td><%= d.id %></td>
        <td><%= d.data %></td>
      <% end %>
    </tr>
  <% end %>
</table>

I assume here @a contains all the years other arrays may contain (based on query). If it's not the case, then you first need to create full array of years:

<% years = (A.keys + B.keys + C.keys + D.keys).uniq %>
<table>
  <% years.each do |year| %>
    <% a = A[year] %>
    <!-- the rest is the same, as above -->
  <% end %>
</table>

Upvotes: 1

Related Questions