Iterating through attributes with index in ruby - ruby-on-rails

How can i add index to iteration on attributes in ruby?
<% #child.toys.attributes.each do |attr_name, attr_value| %>
I have tried with each_with index:
<% #child.toys.attributes.each_with_index do |attr_name, attr_value| %>
But where would the index go in?

You could do this
<% #child.toys.attributes.each_with_index do |(attr_name, attr_value), idx| %>
For more details possible-to-access-the-index-in-a-hash-each-loop

.each_with_index appends the index variable:
%w(cat dog wombat).each_with_index {|item, index|
hash[item] = index
}
hash #=> {"cat"=>0, "dog"=>1, "wombat"=>2}
In your example:
<% #child.toys.attributes.each_with_index do |key,value,index| %>
<%= key %>
<%= value %>
<%= index %>
<% end %>
Toys needs to be a member object (attributes won't work on a collection).
-
I also tested with just declaring "key", as follows:
<% #child.toys.attributes.each_with_index do |attr,index| %>
<%= attr[0] %>
<%= attr[1] %>
<%= index %>
<% end %>
attr is returned as an array in this instance, where the key/value is used as 0 and 1 elements of the array respectively.

Related

RoR iterate through a group/each_slice

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.

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

How can I loop through and Save values into an array

The following loop goes through the sales column and lists all 4 existing product values, like 19.99 19.99 3.99 3.99 to the corresponding user id.
<% #sales.each_with_index do |sale, index| %>
<% if current_user.id == sale.user_id %>
<% price = Warehouse.where(:product => sale.product).pluck(:mrr) %>
<%= value = price.split(',').join('.').to_f %>
<% else %>
<% end %>
Now I want to save the results/values into a new global variable and add up each out of "value". So the result of 19.99 19.99 3.99 3.99 should be 47.96.
I'm completely lost. Any Ideas?
You could do something like this:
<% total = 0 %>
<% #sales.each_with_index do |sale, index| %>
<% if current_user.id == sale.user_id %>
<% price = Warehouse.where(:product => sale.product).pluck(:mrr) %>
<%= value = price.split(',').join('.').to_f %>
<% total += value %>
<% end %>
<% end %>
<%= "Total is #{total}" %>
It is highly questionable to have code like this in the view though. You could get prices and calculate totals in your controller instead.
Also note that you are missing an end. I changed the unneeded else to an end.
In your controller you can create a instant variable prefixed by # so it can be used throughout your view
For example in your controller
#total_value = 0
And in your view
<%#sales.each_with_index do |sale, index| %>
<% if current_user.id == sale.user_id %>
<% price = Warehouse.where(:product => sale.product).pluck(:mrr) %>
<%= value = price.split(',').join('.').to_f %>
<% #total_value += value %>
<% else %>
<% end %>
You shouldn't add that kind of logic in your view. Create a view object class (that the controller instantiates) too handle all of this. You also probably can do something like:
user.sales.each do |sale|
total += find_price(sale)
# do more stuff
end
If you are asking 'if current_user.id == sale.user_id' then you most likely doing it wrong.
In that view object you could have a hash that has all the prices you want to show and iterate over that in your view.

Fill hash with checkboxlist (key) and dropdown (value) doesn't work? In ruby on rails

I am implementing a checkboxlist with some items and next to each item there is a dropdown. These two things hang together and what i want to do is to create a hash, the key is the value or id from the checked item, the value is the value of the selected item in the dropdown.
This is what i have:
view:
<% #groups.each do |group| %>
<li>
<%= check_box_tag 'group[]', group.id -%>
<%= h group -%>
<%= select_tag 'role_group[group.id][]', options_for_select(#roles) %>
</li>
<% end %>
controller:
#selected_groups = Group.find(params[:group])
#selected_roles = params[:role_group]
#roleskeys = #selected_roles.keys
Now if i show #roleskeys , he always just say group.id. So this is not correct, this is just the string. Somebody who knows what i am doing wrong?
Try it this way:
<% #groups.each do |group| %>
<li>
<%= check_box_tag 'group[][id]', group.id -%>
<%= h group -%>
<%= select_tag 'group[][group_id]', options_for_select(#roles) %>
</li>
<% end %>
You will have both together in a Hash.

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