RoR iterate through a group/each_slice - ruby-on-rails

I'm looking to get the last 5 items in an array, but to display each item individually, not as a group.
Here's what I've tried below with no success.
#array = Town.all
<% #array.each_slice(5) do |a| %>
<%= a.first %>
<%= a.second %>
<%= a.third %>
<%= a.fourth %>
<%= a.fifth %>
<% end %>
I can't figure out how to pull out a specific number of items and then to call each individual item.

The method you are looking for is in_groups_of (https://apidock.com/rails/Array/in_groups_of):
<% #towns.in_groups_of(5) do |five_towns| %>
<% five_towns.each do |town| %>
# [...]
<% end %>
<% end %>
Update: Maybe you want only the last 5 elements of the array. If so, you can simply call:
Town.all.last(5)
# => array of (max) 5 Town records

To get the last 5 items of an Array you could use last and then iterate them with each:
<%= #array.last(5).each do |a| %>
...
<% end %>
But it seems that you want to get the last 5 records of a model; in that case, you could try this instead:
#array = Town.limit(5).order('id desc')
<%= #array.each do |a| %>
...
<% end %>
... is there a way that I can have let's say the last 5 records of a
model all within one loop? maybe
<%= #array.each do | a, b, c, d, e| %>
<%= a.description %>
<%= b.description %>
<% end %>
You could use the index of each item instead of using each; for example:
#last_five = #array.last(5)
<%= last_five[0] %>
<%= last_five[1] %>
<%= last_five[2] %>
<%= last_five[3] %>
<%= last_five[4] %>
Although that wouldn't be DRY, so it will be better to stick with each.

Related

Rails loop multiple instance variables on same view

Let say I have a controller Transactions:
#transactions = Transaction.all.group(:type)
#transaction_date_asc = Transaction.all.order(:DATE => :desc).group(:type)
#transaction_date_desc = Transaction.all.order(:DATE => :asc).group(:type)
In my view I need to loop all 3 instances.
Something like this where I want to show newest and oldest amount or discount for each transaction type.
<% #transactions do |transaction|%>
transaction.type.name
<%end%>
<% #transaction_date_asc do |transaction_asc|%>
transaction_asc.amount
<%end%>
<% #transaction_date_desc do |transaction_desc|%>
transaction_desc.amount
<%end%>
<% #transaction_date_asc do |transaction_asc|%>
transaction_asc.discount
<%end%>
<% #transaction_date_desc do |transaction_desc|%>
transaction_desc.discount
<%end%>
How am I supposed to place loops, columns and <%end> in my view?
Someone may come up with a better solution, but from my seat it looks like you need to do a query for each group in your view to get the first date transaction, but on the plus side, you only need one query in the controller for the transactions with the last date.
#transactions = Transaction.group(:type).having('DATE = MAX(DATE)')
In the view...
<% #transactions do |transaction| %>
<% first_transaction = Transaction.where(type: transaction.type).order('transaction_date').first %>
<%= transaction.type.name %>
<%= first_transaction.amount %>
<%= transaction.amount %>
<%= first.transaction.discount %>
<%= transaction.discount %>
<% end %>
However... to keep the logic in the view cleaner you could have an instance method for transaction types that will return the first and last transaction.
class Type << ActiveRecord::Base
def first_transaction
Transaction.where(type: self).order('transaction_date ASC').first
end
def last_transaction
Transaction.where(type: self).order('transaction_date DESC').first
end
end
Then in the controller...
#types = Type.all
then in the view...
<% #types.each do |type| %>
<%= type.name %>
<%= type.first_transaction.try(:amount) %>
<%= type.last_transaction.try(:amount) %>
<%= type.first_transaction.try(:discount) %>
<%= type.last_transaction.try(:discount) %>
<% end %>
The reason I'm suggesting #try is to handle the case of no transactions being present for a specific type.

Dynamically displaying the column values

Here, I have 10 columns i.e., answer1, answer2, answer3, ..., answer10 in the table MgAnswer.
I have to check whether each column value is present or not. Only if it present,then I have to display it in the page.
Im giving column names dynamically within for loop
<% (1..10).each do |i| %>
<% if MgAnswer."answer#{i}".present? %>
<%= MgAnswer."answer#{i}" %>
<% end %>
<% end %>
Im ending up with Syntax error.
You can indeed dynamically invoke methods in ruby, but this is not the syntax. Instead do
<% (1..10).each do |i| %>
<% if MgAnswer.public_send("answer#{i}").present? %>
<%= MgAnswer.public_send("answer#{i}") %>
<% end %>
<% end %>
It should seem like the following:
<% (1..10).each do |i| %>
<%= MgAnswer.send("answer#{i}") %>
<% end %>
Since ruby can't evaluate line as MgAnswer."method". Also you can just skip if condition, because it will be evaluated to empty string "".

checkboxes for all elements in a model

I want to display a checkbox for all elements in a model called MyModel. Here is what I wrote:
<%= MyModel.all.each do |c| %>
<%= check_box_tag(:id) %>
<%= label_tag(:name, c[:name]) %><br>
<% end %>
It does show the checkboxes as expected but at the end, I also get a list of the model content as shown in this screenshot.
Actually, it seems to be related to <%= MyModel.all.each do |c| %> because just printing out simple text still prints the whole model table content at the end:
<%= MyModel.all.each do |c| %>
toto<br>
<% end %>
shows this screenshot
Any idea how to get rid of this list at the end?
Thanks!
<%- MyModel.all.each do |c| %>
<%= check_box_tag(:id) %>
<%= label_tag(:name, c[:name]) %><br>
<% end %>
- - evaluates code.
= - evaluates code and outputs.

Doing basic math in Rails within each "each do" loop and getting the sum

New to Rails! I have products which are associated to a campaign. Each #product has a .price and .orders_count associated to it.
What I wanted to do is multiply the .price with .orders_count for each #product, and add them all up to get a total cost for the #campaign.
Being new to Rails, wasn't sure how to do the write syntax and had the following in the view. This does the first piece, but does not add them all up at the end. Thanks for the help!
<% #products.each do |p| %>
<% if p.orders_count? %>
<%= (number_to_currency((p.price) * p.orders_count)) %>
<% end %>
<% end %>
Try setting a variable to keep track of the sum of all products, and add the product to it each time through the loop. Try this:
<% sum = 0 %>
<% #products.each do |p| %>
<% if p.orders_count? %>
<% product = (number_to_currency((p.price) * p.orders_count)) %>
<% sum += product %>
<%= product %>
<% end %>
<% end %>
The sum is: <%= sum %>

Loop Trick - How to show one attribute if...?

I'm looking for a function we can use in a loop to do this:
<% for rink in #rinks_in_region %>
<%= rink.city #Show Only if city (n-1) != n %>
<%= link_to_rink(rink.name+" Ice Rink",rink) %>
<br>
<% end -%>
Basically just show the city only if it's different than the previous one.
Make sense? Thanks for your help!
Alextoul
You could use the group_by method on #rinks_in_region to group rinks by city and then use those groupings to display cities and rinks. It returns a hash mapping the thing you are grouping by, city in this case, to the values in the original collection that are in that group. So:
<% #rinks_in_region.group_by(&:city).each_pair do |city, rinks| %>
<%= city %>
<% rinks.each do |rink| %>
<%= link_to_rink(rink.name+" Ice Rink",rink) %>
<br/>
<% end -%>
<% end -%>
<% prev_city = nil -%>
<% for rink in #rinks_in_region %>
<%= rink.city if rink.city != prev_city %>
<% prev_city = rink.city -%>
<%= link_to_rink(rink.name+" Ice Rink",rink) %>
<br>
<% end -%>
Not a ruby answer, but introduce a new variable, call it 'temp' or something and set that to the current element in your foreach. That way at the beginning of your loop you have access to last loops element.
temp = ''
<% for rink in #rinks_in_region %>
<%= rink.city #Show Only if city != temp %>
<%= link_to_rink(rink.name+" Ice Rink",rink) %>
<br>
temp = city
<% end -%>
temp = ''

Resources