List two columns on ruby - ruby-on-rails

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")

Related

erb:how to filter on resource attribute

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

Rails: Sum column by group

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.

Show attribute value using its id

In my application, I am grouping my objects by an ID. At the moment, I can only display the ID, but I would like to display the attribute value.
A Fixture belongs_to a tournament and a tournament has_many fixtures.
Controller
def index
#fixtures = Fixture.all
#tournament_fixture = #fixtures.group_by {|f| f.tournament_id}
end
View
<% #tournament_fixture.sort.each do |tourn_name, fixture| %>
<%= tourn_name %>
<% fixture.each do |f| %>
<td><%= f.home_team %></td>
<td><%= f.away_team %></td>
<td><%= f.kickoff_time %></td>
</tr>
<% end %>
<% end %>
How can I get
<%= tourn_name %>
to display its corresponding value that is in its :name column?
At the moment in my view for example i get this returned
<tbody>
2
<tr>
<td>Tournament Name</td>
<td>Team 1</td>
<td>Team 2</td>
<td>2000-01-01 14:00:00 UTC</td>
<td><a class="btn btn-success" href="/fixtures/1">view</a></td>
</tr>
</tbody>
The 2 needs to be the value in the :name column
I'd recommend grouping by tournament instead:
#tournament_fixture = #fixtures.group_by(&:tournament)
And then iterate using:
<% #tournament_fixture.sort.each do |tournament, fixture| %>
<%= tournament.name %>
...
<% end %>
You can access the whole object much like you can get the id like this:
def index
#fixtures = Fixture.includes(:tournaments).all
#tournament_fixture = #fixtures.group_by {|f| f.tournament.name}
end
The id is still available as either f.tournament_id or f.tournament.id, should you still need it but I just figured you'd rather group by its name directly. I simply added an includes statement to also load the referenced Tournament objects with your fixtures in one go. Otherwise, Rails would load the tournaments only when you access them one by one.
As an alternative, you could load the Tournaments, including all their the fixtures instead and iterate over the tournaments like this:
Controller
def index
#tournaments = Tournament.includes(:fixtures).all
end
View
<% #tournaments.each do |tournament| %>
<%= tournament.name %>
<% tournament.fixtures.each do |f| %>
<td><%= f.home_team %></td>
<td><%= f.away_team %></td>
<td><%= f.kickoff_time %></td>
</tr>
<% end %>
<% end %>
It seems a bit more natural to me and you don't need to iterate over all fixtures to map them by their tournament.
You can load the fixtures in the right order. There is no need to group then in memory. Remember to include the tournaments to avoid N+1 queries.
# controller
def index
#fixtures = Fixture.order(:tournament_id).includes(:tournaments).all
end
Loading in the right order in the controller makes the view simpler. For the tournament's name just use the association between Fixture and Tournament.
# view
<% #fixtures.each do |fixture| %>
<tr>
<td><%= fixture.tournament.name %></td>
<td><%= fixture.home_team %></td>
<td><%= fixture.away_team %></td>
<td><%= fixture.kickoff_time %></td>
</tr>
<% end %>

serial number with pagination rails

I am using pagination for my index page where I list all the users information like name, email etc. In the table I want to display the serial number in the order [1,2,3...]. If I user the user_id and if I delete the user the number will be missing out of sequence. I use the following code in my view
<% #user.each_with_index do |d, i| %>
<tr>
<td><%= i+1 %></td>
<% if d.profile.present? %>
<td><%= link_to d.profile.first_name+ " "+d.profile.last_name, posts_individualpostlink_path(:id => d.id) %> </td>
<% else %>
<td><%= "No Profile" %></td>
<% end %>
<td><%= d.email %></td>
<% if d.profile.present? %>
<td><%= d.profile.date_of_birth %> </td>
<% else %>
<td><%= "No Profile" %></td>
<% end %>
</tr>
<% end %>
</table>
<%= will_paginate #user %>
when I am going to the second page again the serial number starts with [1,2,....]. Per Page if i am giving 10 users, the second page should show [11, 12, 13,..... in the table.
Can anyone help me to do this. Thanks
Try with
<%
count = ((params[:page] || 1).to_i - 1) * 10
#user.each_with_index do |d, i| %>
<tr>
<td><%= count + i %></td>
Before answering question, small emotional note: stop using single letter variables in Your code. It makes it completely unreadable.
Why not use <% #user.each_with_index do |user, idx| %> ? Now in You code block it's easy to understand that You always refer to user.
Now the answer. Will paginate add page parameter to the paging links. So in You controller You should be able to do this:
#page = params[:page] || 1
After that use it to calculate correct number in Your view:
<td><%= (#page - 1) * number_of_items_on_page + i+1 %></td>

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