Rails summary with sub-totals by date - ruby-on-rails

I'm writing my first Rails view that summarizes data by date. I want one row for each date with the columns summarized for that date.
I have been able to make it work. But, it's awkward coding. This is what I have:
<h3>Carwings Daily Summary</h3>
<table class="display dataTable table table-striped table-bordered" id="dataTable2">
<thead>
<tr>
<th>Date</th>
<th># Trips</th>
<th>E Consumption (kWh)</th>
<th>E Regeneration (kWh)</th>
<th>E Total (kWh)</th>
<th>Distance (Miles)</th>
<th>Energy Economy (Miles/kWh)</th>
<th>CO2 Emission Reduction (lbs)</th>
</tr>
</thead>
<tbody>
<% trips = 0 %>
<% consumption = 0 %>
<% regen = 0 %>
<% total = 0 %>
<% distance = 0 %>
<% economy = 0 %>
<% emissions = 0 %>
<% sumdate = nil %>
<% #carwings.each.with_index do |carwing, index| %>
<% sumdate = carwing.date if index == 0 %>
<% if carwing.date == sumdate %>
<% trips = trips + 1 %>
<% consumption = consumption + carwing.e_consumption %>
<% regen = regen + carwing.e_regen %>
<% total = total + carwing.e_total %>
<% distance = distance + carwing.distance %>
<% economy = economy + carwing.economy %>
<% emissions = emissions + carwing.emission_reduction %>
<% else %>
<tr>
<td class="nowrap"><%= sumdate %></td>
<td><%= trips %></td>
<td><%= consumption %></td>
<td><%= regen %></td>
<td><%= total %></td>
<td><%= distance %></td>
<td><%= economy %></td>
<td><%= emissions %></td>
</tr>
<% trips = 1 %>
<% consumption = carwing.e_consumption %>
<% regen = carwing.e_regen %>
<% total = carwing.e_total %>
<% distance = carwing.distance %>
<% economy = carwing.economy %>
<% emissions = carwing.emission_reduction %>
<% sumdate = carwing.date %>
<% end %>
<% end %>
<tr>
<td class="nowrap"><%= sumdate %></td>
<td><%= trips %></td>
<td><%= consumption %></td>
<td><%= regen %></td>
<td><%= total %></td>
<td><%= distance %></td>
<td><%= economy %></td>
<td><%= emissions %></td>
</tr>
</tbody>
</table>
There's got to be a better way.
Suggestions?
Thanks for the Help!!

Some minor stuff:
trips = trips + 1
# is better written as:
trips += 1
erb tags can be multiline eg:
<% if blah
do_something
something else
end %>
If you are setting multiple variables to the same value, you don't need to repeat them each line eg:
trips = consumption = regen = 0
yes - this is minor stuff - but clean up the minor stuff and it'll give you a better shape of what you're trying to do.
perhaps if you gave us your logic in descriptive pseudocode (so we aren't just guessing what you're trying to do) then we can give you better structure to your code too. :)
Personally: I'd recommend setting up all this data in your controller (or even your carwing model) before it ever hits the view. I'd use a hash - whee the carwnig.date is the key, and all the rest is another hash eg:
data = Hash.new({:trips => 0, :consumption => 0}) # google initialising hashes
#carwings.each do |carwing|
data[carwing.date][:trips] += 1
data[carwing.date][:consumption] += carwing.e_consumption
# etc
end

Related

Rails - Subtotaling based on if statements

<h1> What it looks like currently</h1><br>
<table>
<thead>
<tr>
<th>Month</th>
<th>Month Total</th>
<th>Written</th>
<th>Verbal</th>
<th>Probable 75%</th>
<th>Probable 25%</th>
<th>Speculative</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<tr><td>Jan 2017</td> <td>50</td><td>0</td><td>50</td><td>0</td><td>0</td><td>0</td></tr>
<tr> <td>Feb 2017</td> <td>100</td><td>0</td><td>100</td><td>0</td><td>0</td><td>0</td></tr>
<tr><td>Mar 2017</td> <td>700</td><td>0</td><td>700</td><td>0</td><td>0</td><td>0</td></tr>
<tr><td>Jan 2017</td> <td>700</td><td>700</td><td>0</td><td>0</td><td>0</td><td>0</td></tr>
<tr><td>Feb 2017</td> <td>5000</td><td>5000</td><td>0</td><td>0</td><td>0</td><td>0</td></tr>
<tr><td>Jan 2017</td> <td>500</td><td>0</td><td>0</td><td>500</td><td>0</td><td>0</td></tr>
<tr><td>Jan 2017</td> <td>5000</td><td>0</td><td>0</td><td>0</td><td>0</td><td>5000</td></tr>
</tbody>
</table>
<h1> What I need it look like </h1><br>
<table>
<thead>
<tr>
<th>Month</th>
<th>Month Total</th>
<th>Written</th>
<th>Verbal</th>
<th>Probable 75%</th>
<th>Probable 25%</th>
<th>Speculative</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<tr><td>Jan 2017</td> <td>1250</td><td>700</td><td>50</td><td>500</td><td>0</td><td>5000</td></tr>
<tr> <td>Feb 2017</td> <td>5100</td><td>5000</td><td>100</td><td>0</td><td>0</td><td>0</td></tr>
<tr><td>Mar 2017</td> <td>700</td><td>0</td><td>700</td><td>0</td><td>0</td><td>0</td></tr>
</tbody>
</table>
I'm a bit of a coding noob so I could be going about this all the wrong way, but I've muddled my way through so far...until now.
What I need is to subtotal the months so the values all appear on the relevant line: Here
The code I used for that is:`
<% #months.each do |t| %>
<tr>
<td><%= t.monthYear %> </td> <td><%= t.monthValue %></td>
<% if(t.destination.status == "Written") %>
<td><%= t.monthValue %></td>
<% else %>
<td>0</td>
<% end %>
<% if(t.destination.status == "Verbal") %>
<td><%= t.monthValue %></td>
<% else %>
<td>0</td>
<% end %>
<% if(t.destination.status == "Probable 75%") %>
<td><%= t.monthValue %></td>
<% else %>
<td>0</td>
<% end %>
<% if(t.destination.status == "Probable 25%") %>
<td><%= t.monthValue %></td>
<% else %>
<td>0</td>
<% end %>
<% if(t.destination.status == "Speculative") %>
<td><%= t.monthValue %></td>
<% else %>
<td>0</td>
<% end %>
</tr>
<% end %>`
The models:
Destination:
class Destination < ActiveRecord::Base
belongs_to :tag
has_many :months
end
Month:
class Month < ActiveRecord::Base
belongs_to :destination
belongs_to :tag
end
The months have 3 fields: monthYear, monthValue & Destination_id.
Destination has Status and others which I don't think are relevant.
I've been searching and used:
% #months.select(:monthYear, :monthValue, :destination_id).group(:monthYear).each do |t| %> and different variations including trying to sum by :monthValue but end up with this: Subtotaled months but not values.
Thanks in advance!
So I figured it out, but the answer definitely isn't pretty! I appreciate this could be done a lot clearer, but I've muddled my way through! Here's the code I used and the result:
View
<tbody>
<% #months.group(:monthYear).each do |z| %>
<% this_thing = 0 %>
<% this_thing2 = 0 %>
<% this_thing3 = 0 %>
<% this_thing4 = 0 %>
<% this_thing5 = 0 %>
<% #testing.each do |b| %>
<% if (z.monthYear == b.monthYear) && (b.destination.status == "Written") %>
<% this_thing = this_thing + b.monthValue %>
<% end %>
<% if (z.monthYear == b.monthYear) && (b.destination.status == "Verbal") %>
<% this_thing2 = this_thing2 + b.monthValue %>
<% end %>
<% if (z.monthYear == b.monthYear) && (b.destination.status == "Probable 75%") %>
<% this_thing3 = this_thing3 + b.monthValue %>
<% end %>
<% if (z.monthYear == b.monthYear) && (b.destination.status == "Probable 25%") %>
<% this_thing4 = this_thing4 + b.monthValue %>
<% end %>
<% if (z.monthYear == b.monthYear) && (b.destination.status == "Speculative") %>
<% this_thing5 = this_thing5 + b.monthValue %>
<% end %>
<% end %>
<td><%=z.monthYear %></td>
<td><%= this_thing + this_thing2 + this_thing3 + this_thing4 + this_thing5 %> </td>
<td><%= this_thing %></td>
<td><%= this_thing2 %></td>
<td><%= this_thing3 %></td>
<td><%= this_thing4 %></td>
<td><%= this_thing5 %></td>
<td><%= (this_thing * 1)+(this_thing2 * 1)+(this_thing3 *0.75)+(this_thing4 * 0.25)+(this_thing5 * 0)%></td>
</tr>
<% end %>
</tbody>
Tags Controller
def index
#months = Month.all
#testing = Month.joins(:destination).includes(:destination).select("months.monthYear, months.monthValue, destination_id, destinations.status")
end
The end result!

Capybara check if no selector has text of numbers greater than 500

I want to check if there are 0 instances of numbers greater than 500 in all of the rows of a table.
The table looks like this:
<% #trips.each do |trip| %>
<tr class="trip-row" data-categories= "<%= #categories.map(&:name).join(":") %>">
<td id="ranking"><%= #trips.index(trip) + 1 %></td>
<td id="trip-title"> <%= trip.title %> </td>
<td><%= trip.departure_city %></td>
<td><%= trip.arrival_city %></td>
<td><%= trip.departure_airline %></td>
<td><%= trip.short_description %></td>
<td><%= trip.departure_date.strftime("%b %d, %Y, %I:%M") %></td>
<td><%= trip.return_date.strftime("%b %d, %Y, %I:%M") %></td>
<td><%= trip.price %></td>
<td><%= link_to "Details", real_trip_path(trip, info: { departure_date: trip.departure_date, return_date: trip.return_date, price: trip.price }), class: "btn btn-info" %></td>
</tr>
<% end %>
Can I write this:
within all(".trip-row") do
refute page has.content? #number greater than 500?
end
You can evaluate values in each cell rather than row by row.
page.all(.'trip-row td').each do |c|
#evaluate here
end
You'll probably want to use regex to pull the numbers out from each cell, then evaluate from there using an rspec expectation.

Rails create new records based on checked records

I have a table showing time entries (events) related to a workorder.
The user can enter a check on any of the table rows.
For each checked row, I want to create a new record in the invtime table.
invtime belongs_to :event
event has_many :invtimes
This is the table:
<table>
<thead>
<tr>
<th>Title</th>
<th>Employee</th>
<th>Date</th>
<th>Hours</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% Event.where("workorder_id = ?", Invoice.find(#invoice).workorder_id).where("billed = ?", false).each do |event| %>
<tr>
<td><%= check_box_tag(:add_record) %></td>
<td><%= event.title %></td>
<td><%= event.employee.employee_full_name %></td>
<td><%= event.starts_at.strftime("%m/%d/%Y") %></td>
<td><%= event.hours %></td>
<td></td>
</tr>
<% end %>
</tbody>
</table>
I'm not sure how to process the returned page with the checkboxes checked.
Should I use Javascript (coffeescript)? Or can I do it with Ruby?
This should do it:
<tbody>
<%= form_tag(your_path_helper) do %>
<% Event.where("workorder_id = ?", Invoice.find(#invoice).workorder_id).where("billed = ?", false).each do |event| %>
<tr>
<td><%= check_box_tag 'event_ids_to_save[]', value: event.id, checked: Invtime.exists?(event_id: event.id) %></td>
<td><%= event.title %></td>
<td><%= event.employee.employee_full_name %></td>
<td><%= event.starts_at.strftime("%m/%d/%Y") %></td>
<td><%= event.hours %></td>
<td></td>
</tr>
<% end %>
<tr><td colspan='6'><%= submit_tag %></td></tr>
<% end %>
</tbody>
The corresponding action of the controller responding to the form_tag submit:
def action_of_the_form_tag
params[:event_ids_to_save].each do |event_id|
event = Event.where(id: event_id)
# do your logic here
end
end

rails: organizing data into a table using for

I have the following view:
<table class="fixed">
<tr>
<th>Student Name</th>
<!-- create as many <th> as there are evaluations -->
<% #eval_count.times do |i| %>
<th>Evaluation <%= i+1 %></th>
<% end %>
<th>Student Average <br />(for this goal)</th>
</tr>
<% for eval in #evals %>
<tr class="<%= cycle("odd", "even", name: "evals")%>">
<!-- eval returns { s_id [eval],[eval]} -->
<td><%= eval[1].first.student.name%></td>
<!-- in each student's row, print the score for each consecutive evaluation -->
<% #eval_count.times do |i| %>
<td><%= eval[1][i].score %><% #ss_scores << eval[1][i].score %></td>
<% end %>
<td><%= #ss_scores %></td>
</tr>
<% reset_cycle("evals") %>
<% end %>
</table>
<% #ss_scores.in_groups(#student_count, false) do |group|%>
<%= (group.sum.to_f/group.size).round(2) %>
<% end %>
which renders the following:
I want to put the average for each student in the last column, but #ss_scores is a variable and so calling anything on it doesn't work. But when the for loop has finished, #ss_scores can be worked with nicely as in the bottom of the screenshot. Any idea how to do this better?
Try emptying the array everytime, using [] and calculate the average inline, like below
<td><%= #ss_scores.inject(0.0) { |sum, el| sum + el } / #ss_scores.size %></td>
<% #ss_scores = [] %>
-
<% for eval in #evals %>
<tr class="<%= cycle("odd", "even", name: "evals")%>">
<!-- eval returns { s_id [eval],[eval]} -->
<td><%= eval[1].first.student.name%></td>
<!-- in each student's row, print the score for each consecutive evaluation -->
<% #eval_count.times do |i| %>
<td><%= eval[1][i].score %>
<% #ss_scores << eval[1][i].score %>
</td>
<% end %>
<td><%= #ss_scores.inject(0.0) { |sum, el| sum + el } / #ss_scores.size %></td>
<% #ss_scores = [] %>
</tr>
<% reset_cycle("evals") %>
<% end %>

Using a if statement in a looped table rails

I have two models, one with cards and another with their associated rewards programs. I'm showing all of them in a table with a conditional if statement in some of the columns but I can't figure out why an if else statement screws up my columns. I posted two examples one that works and one that doesn't. I need the second one to work to add some additional functionality
This example works
<table>
<tr>
<th>Card</th>
<th>General Rewards</th>
<th>Gas Amount</th>
<th>Movies Amount</th>
<th>Museums Amount</th>
<th>Theme Park Amount</th>
<th>Restaurant Amount</th>
<th>Department Store Amount</th>
</tr>
<% #cards.each do |card| %>
<tr>
<td><%= card.name %></td>
<td><%= card.general_rate %> </td>
<% card.rewards.each do |category| %>
<% if category.name.downcase == "gas" %>
<td><%= category.threshold_check(#gas) %></td>
<% end %>
<% if category.name.downcase == "movies" %>
<td><%= category.threshold_check(#movies) %></td>
<% end %>
<% if category.name.downcase == "museums" %>
<td><%= category.threshold_check(#museums) %></td>
<% end %>
<% if category.name.downcase == "theme parks" %>
<td><%= category.threshold_check(#theme_parks) %></td>
<% end %>
<% if category.name.downcase == "restaurants" %>
<td><%= category.threshold_check(#restaurants) %></td>
<% end %>
<% if category.name.downcase == "department stores" %>
<td><%= category.threshold_check(#department_stores) %></td>
<% end %>
<% end %>
</tr>
<% end %>
</table>
This adds extra columns to the end
<table>
<tr>
<th>Card</th>
<th>General Rewards</th>
<th>Gas Amount</th>
<th>Movies Amount</th>
<th>Museums Amount</th>
<th>Theme Park Amount</th>
<th>Restaurant Amount</th>
<th>Department Store Amount</th>
</tr>
<% #cards.each do |card| %>
<tr>
<td><%= card.name %></td>
<td><%= card.general_rate %> </td>
<% card.rewards.each do |category| %>
<td><%= category.name.downcase == "gas" ? category.threshold_check(#gas) : 0 %></td>
<td><%= category.name.downcase == "movies" ? category.threshold_check(#movies) : 0 %></td>
<td><%= category.name.downcase == "museums" ? category.threshold_check(#museums) : 0 %></td>
<td><%= category.name.downcase == "theme parks" ? category.threshold_check(#theme_parks) : 0 %></td>
<td><%= category.name.downcase == "restaurants" ? category.threshold_check(#restaurants) : 0 %></td>
<td><%= category.name.downcase == "department stores" ? category.threshold_check(#department_stores) : 0 %></td>
<% end %>
</tr>
<% end %>
</table>
If you will notice the main difference between your 2 versions is that the first one if your conditionals dont comply, you will not issue a <td></td>
On the other hand your second version does have <td></td> no matter if the conditionals are true or not.
Maybe that could be the source for your extra columns.
P.S. In your first example I think you have a typo but <%= category.threshold_check(#movies) %> doesn't have an opening <td> and it's closing </td> is outside the if statement.

Resources