How to sum object column? - ruby-on-rails

I need to make sum of column.
I think problem is in class, in action where I take performance_reports.
I have associsations, so I get all reports related to user by next code:
#performance_reports = Array.new
current_user.websites.each do |website|
reports = website.performance_reports
reports.each do |report|
#performance_reports.push(report)
end
end
In my view I'm printig each report and in the bottom I want to print summary of column.
Here is view:
<% #performance_reports.each do |performance_report| %>
<tr>
<td><%= performance_report.impressions %></td>
<td><%= performance_report.clicks %></td>
<td><%= performance_report.conversions %></td>
</tr>
<% end %>
<tr>
<td><%= #performance_reports.count(:clicks)%></td>
<td><%= #performance_reports.count(:conversions)%></td>
</tr>
All - clicls, conversions - are integer type.
This code is printing, that summary is 0.
I have two questions: how to sum integers and how to sum not integer columns, which are not saving to database?

you can use the method sum for this
#performance_reports.sum(:clicks)
it will also sum not integer also as it will return non integer type, to convert it in integer call like this
#performance_reports.sum(:clicks).to_i

Related

How to dynamically generate checkboxes on the view and submit to controller?

I send a collection to my view and iterate over it. Each iteration has a checkbox as well as two text fields. I want to be able to submit selected items, but also submit the values in the text field as an update as well.
<% #lots.each_with_index do |lot, index| %>
<tr>
<td><%= lot.lot_code %></td>
<td ><%= check_box_tag "lots[][lot_id]", lot.id, false, %></td>
<td><%= text_field_tag "lots[][seal_num]", lot.seal_number %></td>
<td><%= text_field_tag "lots[][contr_num]", lot.container_number %></td>
</tr>
<% end %>
My #lots collection has three rows:
{id: 2, container_number: "container#0002", seal_number: "seal#0002"}
{id: 6, container_number: "container#0006", seal_number: "seal#0006"}
{id: 11, container_number: "container#00011", seal_number: "seal#00011"}
(apologies if that is not proper hash syntax)
My problem is that if I check items 1 and 3, the parameter string shows the following:
"lots"=>[{"lot_id"=>"2", "seal_num"=>"seal 0002", "contr_num"=>"container#0002"},
{"seal_num"=>"Seal-006", "contr_num"=>"container #006", "lot_id"=>"11"},
{"seal_num"=>"Seal-0011", "contr_num"=>"container #0011"}]
The problem is that lot_id = 11 should be the 3rd item in the array, not the second. For some reason, because item #2 is not selected, the empty lot_id element is being populated by the next one in the sequence.
How do I make sure the selected IDs are in the same elements as the other attributes? Or how do I make sure the non-selected items don't even end up on the parameter string?
Edit: I have also tried the following:
<% #lots.each_with_index do |lot, index| %>
<tr>
<td><%= lot.lot_code %></td>
<td ><%= check_box_tag "lots[#{index}][lot_id]", lot.id, false, %></td>
<td><%= text_field_tag "lots[#{index}][seal_num]", lot.seal_number %></td>
<td><%= text_field_tag "lots[#{index}][contr_num]", lot.container_number %></td>
</tr>
<% end %>
And I get this on the following parameter string:
lots"=>{"0"=>{"lot_id"=>"2", "seal_num"=>"seal 0002", "contr_num"=>"container#0002"},
"1"=>{"seal_num"=>"Seal-006", "contr_num"=>"container #006"},
"2"=>{"lot_id"=>"19", "seal_num"=>"Seal-0011", "contr_num"=>"container #0011"}}
This maintains the integrity of the rows as desired, but I later get a "TypeError: no implicit conversion of String into Integer" later on in processing.
Edit 2: Realized the solution in the edit created a hash, and my code was looking to access an array. So when the hash was iterated over, I was errantly accessing the key, an integer, rather than the value.

How to Show Sum of Column in Rails

I want to display the sum of a column name "money" in my model Earning.
In the rails console, I can easily get the sum I want Earning.sum(:money) and it shows the sum.
earnings_controller.rb
def index
#earnings = Earning.sum(:money)
end
index.html.erb
<p id="notice"><%= notice %></p>
<h1>Earnings</h1>
<table>
<thead>
<tr>
<th>Money</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #earnings.each do |earning| %>
<tr>
<td><%= earning.money %></td>
<td><%= link_to 'Show', earning %></td>
<td><%= link_to 'Edit', edit_earning_path(earning) %></td>
<td><%= link_to 'Destroy', earning, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Earning', new_earning_path %>
It keeps throwing this error
NoMethodError in Earnings#index
What I've tried so far
I am stumped. I've tried changing the index action to #earnings = earnings.sum(:money) and that gave me this error "NameError in EarningsController#index". I also saw a similar problem here but since I think the issue is in my index.html.erb, it didn't help much. As I said earlier the code works in the Rails Console.
Thank you in advance for any help.
So you are not using #earnings in a proper way, in your view you use earnings as a collecion of objects, but in controller #earnings are defined as a sum of money but you are not using it, if you really need this sum, you can set two instance variables fiest #earnings = Earning.all and the second one #money_sum = Earnings.sum(:money) and then you can display somewhere your sum as = #money_sum, then you can iterate by #earnings to create some linka in your view
It looks like you want to do something like this.
First in your controller you want to get all earnings records.
def index
#earnings = Earning.all
end
Then in your view you iterate over all #earnings and spit out earnings.money as single value for each of your record.
If you want to get total of all earnings somewhere, you can do #earnings.sum(:money), which will basically give you single value as total of all earnings - Earning.all.

List two columns on ruby

Trying to show a list of items. I have items and calibrations. I want show all the data from items + date_cal_expired (select the max date, because one item can have many calibrations) from calibrations.
In the controller
#items = Item.includes(:calibrations).where('calibrations.date_cal_expired <= ?' , now)
In the index
<% #items.each do |item| %>
<tr>
<td><%= item.den_cont %></td>
<td><%= item.marca %></td>
<td><%= item.modelo %></td>
<td><%= item.nro_serie %></td>
<td><%= item.genre.genre %></td>
<td><%= item.state.state %></td>
What should I do to show date_cal_expired??
I don't know how to show data from other table
Hope you understand. Tks!
If you want to perform single query:
Item.select("items.*, c.date_cal_expired AS date_cal_expired")
.joins("LEFT JOIN calibrations AS c ON c.item_id = item.id
WHERE NOT EXISTS(SELECT 1 FROM calibrations AS j
WHERE c.item_id = j.item.id
AND t.date_cal_expired < j.date_cal_expired)")
Now the date_cal_expired is an item's attribute:
<% item.date_cal_expired %>
Or simple solution:
<% item.calibrations.map(&:date_cal_expired).try(:max) %>
item.calibrations.pluck(:date_cal_expired).max
You have already showed data from other table by using
<td><%= item.genre.genre %></td> // this way you go to table genre and display field genre
If you want data from other table you should just put
<td>
<% item.calibrations.each do |calibration| %>
<%= calibration.field_1 %>
// ....
<%= calibration.field_n %>
<% end %>
</td>
item.calibrations.max("your value")

each loop: show item once and sum quantity

I currently am using this peice of code to loop through ordered items for a specific date
<tr>
<th>Item</th>
<th>Quantity</th>
</tr>
<% #demand.each do |d| %>
<% d.demand_items.each do |item| %>
<tr>
<td><%= item.item.name %></td>
<td><%= #item_count %></td>
</tr>
<% end %>
<% end %>
Currently if item 1 is ordered more than once, it shows up multiple times in the list. I just want it to show up once and have a number next to it to show how many are ordered. For example, if item_1 has a quantity of 5 in demand_1 and item_1 has a quantity of 10 in demand_2, the result should be:
item_1 .... 15
Thanks!
This should do it:
<tr>
<th>Item</th>
<th>Quantity</th>
</tr>
<% #demand.flat_map(&:demand_items).group_by(&:item).each do |item, demands| %>
<tr>
<td><%= item.name %></td>
<td><%= demands.map(&:quantity).inject(:+) %></td>
</tr>
<% end %>
Hope this helps!
Some explanation:
#demand.flat_map(&:demand_items)
# equivalent: (long version)
#demand.map{ |demand| demand.demand_items }.flatten
# retrieves all demand_items of each demand in the #demand list
# flatten the result (which is a double-dimension array)
demands.map(&:quantity)
# sends .quantity call to each element of the demands list
# and put it in an array (so this returns an array of quantity of each demand)
# equivalent: (long version)
demands.map{ |demand| demand.quantity }
demands.map(&:quantity).inject(:+)
# the inject(:+) will inject the method + (add) between each element of the array
# since the array is a list of quantities
# the inject(:+) sums each quantity of the list
I would try and get the uniq items and then count them while looping, something like:
(#demand.demand_items.sort.uniq).each do |d|
d.item_name
d.demand_items.count
end
This is untested pseudo code.

Compute multiple distinct averages

I'm fairly new to rails, and am still getting used to putting together methods. I'm currently trying to create a method that averages distinct data from multiple columns. I'd like to do it all in one method so that I can display the information easily in an html table.
Currently I have this in my model:
def averagedonate
scores.group(:donatedate).average('donateamount')
scores.group(:donatedate).average('rating')
end
I'd like to be able to use them in a table like this:
<% #averagedonate.each do |donatedate, donateamount, rating| %>
<tr>
<td><%= donatedate %></td>
<td><%= donateamount %></td>
<td><%= rating %></td>
</tr>
How do I change my averagedonate method to do this? Thanks in advance!
I haven't tested, but something to this effect should work
def averagedonate
scores.select("
AVG(donateamount) as avg_donateamount,
AVG(rating) as avg_rating,
donatedate
")
.group(:donatedate)
end
Then use it like this
<% #averagedonate.each do |item| %>
<tr>
<td><%= item.donatedate %></td>
<td><%= item.avg_donateamount %></td>
<td><%= item.avg_rating %></td>
</tr>
<% end %>

Resources