I created this code that pulls the information I need.
def index
#votes = Vote.all
#originalitysum = Vote.group(:widget_id).sum(:originality)
end
It returns a hash:
{188=>5, 160=>2}
I now need to match the key to the widget_id and return the value. I.E:
If the widget_id is 188 return 5.
<% #votes.group(:widget_id).each do |vote| %>
<tr>
<td><%= vote.widget.name %></td>
<td><%= vote.widget.store %></td>
<td><%= %></td> <!-- This needs to be the total Originality -->
<td><%= vote.interest %></td>
<td><%= vote.rating %></td>
</tr>
<% end %>
I'm open to changing this if some other way makes more sense.
You can get the originality sum with #originalitysum[vote.widget.id]
Figured it out.
Controller
def index
#votes = Vote.all
#originalitysum = Vote.select([:widget_id, :originality]).group('widget_id').sum(:originality)
#votecount = Vote.group(:widget_id).count(:originality)
#votes = Vote.select(:widget_id,
"SUM(originality) as originality_sum",
"SUM(interest) as interest_sum",
"SUM(rating) as rating_sum").group(:widget_id).order("rating_sum DESC")
end
The view
<% #votes.group(:burger_id).each do |vote| %>
<tr>
<td><%= vote.widget.name %></td>
<td><%= vote.widget.store %></td>
<td><%= vote.originality_sum %></td>
<td><%= vote.interest_sum %></td>
<td><%= vote.rating_sum %></td>
</tr>
<% end %>
Thanks to this answer in this link, I was able to parse it together.
Group by a column and then get the sum of another column in Rails
The added bonus is that it allowed me to easily sum the other columns as well.
Related
Good afternoon. I am new to ruby and trying to build my first application.
I am using sqlite database and rails 5.0.
I have a model called Person that has the first name, last name and date of birth as attributes.
On the page where I list people I want to add the age of the people and obtain an average of the ages of the people
My controller looks like this:
before_action :set_persona, only: %i[ show edit update destroy ]
# GET /personas or /personas.json
def index
#persona = Persona.order("cast(strftime('%m', fecha_nacimiento) as integer)")
end
And my view like this
<table>
<thead>
<tr>
<th>Nombre</th>
<th>Apellido</th>
<th>Fecha nacimiento</th>
<th>Dni</th>
<th>Edad</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #persona.each do |persona| %>
<tr>
<td><%= persona.nombre %></td>
<td><%= persona.apellido %></td>
<td><%= persona.fecha_nacimiento %></td>
<td><%= persona.dni %></td>
<td><%= Time.now.year - persona.fecha_nacimiento.year %></td>
<td><%= link_to 'Detail', persona %></td>
<td><%= link_to 'Edit', edit_persona_path(persona) %></td>
</tr>
<% end %>
</tbody>
</table>
<p>El promedio de edad de las personas es: </p>
Since I don't have a field in the database called "age" I can't understand how I can achieve the result.
The objective would be to iterate through each of the people and divide it by the length of it, or is there an easier way?
Please excuse my ignorance, thank you very much in advance.
What you want to do is select your calculated column and give it an alias:
def index
#persona = Persona.select(
Persona.arel_table[Arel.star], # personas.*
"cast(strftime('%m', fecha_nacimiento) as integer) as age"
)
.order(age: :desc)
end
Any columns you select will be available in the resulting model instances as attributes:
<table>
<thead>
<tr>
<th>Nombre</th>
<th>Apellido</th>
<th>Fecha nacimiento</th>
<th>Dni</th>
<th>Edad</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #persona.each do |persona| %>
<tr>
<td><%= persona.nombre %></td>
<td><%= persona.apellido %></td>
<td><%= persona.fecha_nacimiento %></td>
<td><%= persona.dni %></td>
<td><%= persona.age %></td>
<td><%= link_to 'Detail', persona %></td>
<td><%= link_to 'Edit', edit_persona_path(persona) %></td>
</tr>
<% end %>
</tbody>
</table>
The easiest way to implement what you're asking is to do the operation within the view. This kind of breaks MVC but it's the fastest.
<% edades = 0 %>
<% #persona.each do |persona| %>
<% edades += Time.now.year - persona.fecha_nacimiento.year %>
<!-- ... the rest of the view code -->
<% end %>
<% average = edades.to_d / #persona.length # need to typecast to decimal so you can have fractionals %>
To do this in an MVC manner, you will have to do the computation in the controller.
def index
#persona = Persona.order("cast(strftime('%m', fecha_nacimiento) as integer)")
#average = #persona.collect { |p| Time.now.year - p.fecha_nacimiento.year }.sum / #persona.length.to_d
end
It would be easier to implement an age method in Person model so you can just call the method instead.
class Person
def edad
Time.now.year - fecha_nacimiento.year
end
end
and lastly, the computation for the age is more complex than just current year less birthday year. We use this function (taken from https://stackoverflow.com/a/2357790/365218) to calculate for the age.
def age(dob)
now = Time.now.utc.to_date
now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
end
How can I filter the results based on the resource attribute in .erb file. For example, I would like to display product which price is lower than 50 dollars. The following is current .erb file. The price tag is a string, need to be converted to number.
<% #products.each do |product| %>
<tr>
<td><%= product.title %></td>
<td><%= product.price %></td>
<td><%= product.count %></td>
</tr>
<% end %>
Can I use this in the view? I have undefined method "filter" error.
<% #products.filter { |p| p.price < 50 }.each %>
<tr>
<td><%= product.title %></td>
<td><%= product.price %></td>
<td><%= product.count %></td>
</tr>
<% end %>
The short answer: you can either use select to only select products with a price less than 50 dollars or even partition to split the list into those below and above that price.
Ideally you'd do this outside of the view, though, for example inside your controller or even the model.
Basic filtering (inside view):
#products.select { |p| p.price < 50 }.each do |product|
Or with a scope in the model:
scope :below_price, ->(price) { where("price < ?", price) }
You can use it in the controller:
PRICE_THRESHOLD = 50
def index
#products = Product.below_price(PRICE_THRESHOLD)
end
Hi chaps and chappettes.
<tbody>
<% #orders_outstanding.limit(5).each do |order| %>
<% if order.completed_at.blank? && order.due_date.present? %>
<tr>
<td><%= order.order_number %></td>
<td><%= order.customer %></td>
<td><%= order.printer %></td>
<td><%= order.quantity %></td>
<td><%= order.due_date %></td>
</tr>
<% end %>
<% end %>
</tbody>
I'm using this little bit of code to display my next five orders due to ship. It's showing up in my development environment preview (puma/sqlite) but not on heroku (postgres). Is there any reason heroku doesn't like that formatting?
Thanks
I would put the conditions in the controller to make sure you have 5 that match your conditions:
#orders_outstanding = Order.where(completed_at: nil).where.not(due_date: nil).order("due_date")
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")
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 %>