Sorting in rails app - ruby

I created an app that gives points to students. I want to sort the points in descending order. This is my code.
<% #users.each do |user| %>
<li> <%= user.points%></li>
<%end%>
This code outputs the points from each student, but when I try to add sort! after user.points, it gives me an error. I am not sure where I should do this.

You can go for:
<% #users.sort_by{|u| u.points}.each do |user| %>
<li> <%= user.points%></li>
<%end%>
Or you can go for:
#users=User.order(:points)

Try this:
<% #users.sort_by{|u| u.points}.reverse.each do |user| %>
<li> <%= user.points%></li>
<% end %>
Note: I have used reverese as you have mentioned I want to sort the points in descending order. But It's always good practise to assign data to object in controller as per your requirement.
Do it in controller like:
#users = User.order(points: :desc) # this will fetch users in descending order on basis of points
then in view simply use:
<% #users.each do |user| %>
<li> <%= user.points%></li>
<%end%>
for more info regarding Order

The documentation for Active Record .order is what you need.
http://apidock.com/rails/ActiveRecord/QueryMethods/order
For example:
User.order(:points)
would provide you with users ordered by points. Do the ordering from your controller rather in your view.

Related

Retrieve data using for loop in Ruby

I have a question about using foreach loops in Ruby.
I want to display documents and am using a foreach loop in order to display these documents. It returns an error with the i variable inside of data["response"]["docs"][i]["topic"] which is a JSON string I am iterating over.
I do not understand why that is. Can anyone tell me what I am doing wrong?
If I simply do data["response"]["docs"][0]["topic"] it works fine but not with the i. Why is that?
<%
(0..10).each do |i|
%>
<%= i %> <br/>
<%= data["response"]["docs"][i]["topic"] %>
<%
end
%>
My question is, how many items are there in data["response"]["docs"]? Are there exactly 11? Either way I would use the following code instead:
<% data["response"]["docs"].each_with_index do |item, index| %>
<%= index %>
<br/>
<%= item["topic"] %>
<% end %>
This iterates over the data["response"]["docs"] no matter how many there are (whether is is 1 doc or 20 docs) and stores the value in the variable named item. The each_with_index function gives you the index as well, stored in index, so you can display it later. If you only want the first 11 use:
<% data["response"]["docs"].first(11).each_with_index do |item, index| %>
This will grab a maximum of 11 doc items.
It's hard to tell what might be going wrong because you haven't posted the error, but if you're using a 10-element array, you want to do:
(0..9).each do |i|
With 0-based indexes, you should only use the range from 0-9, rather than 0-10. You may be getting an error because you're trying to access an element that isn't there (i.e. at index 10).
Even better is:
<% data["response"]["docs"].each do |document| %>
<%= document["topic"] %>
<% end %>
or if you need to print the index:
<% data["response"]["docs"].each_with_index do |document, index| %>
<%= index %> <br/>
<%= document["topic"] %>
<% end %>

Outputting data with erb and middleman

I'm wanting to output some data and I'm not sure if it is possible or not without changing my data file. Basically I have a YAML file with the following structure
items:
- category: red
name: super fun times
note: likes fun
- category: red
name: sunshine
note: wear sunglasses
- category: blue
name: crazy face
note: avoid.
What I'm doing is looping through like so
<% data.options.items.each do |q| %>
<h2><%= q.category %></h2>
<p><%= q.name %></p>
<% end %>
I'd like to be able to do is group items by category when it outputs so it would be something like the following.
<h2>red</h2>
<p>super fun times</p>
<p>sunshine</p>
<h2>blue</h2>
<p>crazy face</p>
I pretty much just want to output the category once, list out the items under that category and then when a new category comes up output that one and any relevant data, without having to repeat chunks of code.
An approach you can take is using group_to to cluster the items by their group, resulting in sets of arrays for each category:
<% data.options.items.group_by(&:category).each do |group| %>
<h2><%= group.first %></h2>
<% group.last.each do |item| %>
<p><%= item.name %></p>
<% end %>
<% end %>
In this scenario, running group_by on the collection of items provides an object with the following format:
{"red"=>[{"category"=>"red", "name"=>"super fun times", "note"=>"likes fun"},
{"category"=>"red", "name"=>"sunshine", "note"=>"wear sunglasses"}],
"blue"=>[{"category"=>"blue", "name"=>"crazy face", "note"=>"avoid."}]}
This allows you to then iterate through the object, making it easier to keep the groups separate in the markup.
Hope it helps!

Divide loop iteration in an html.erb file over different sections for enhancing performance

This is part of my code in an html.erb file
<div class="list_carousel">
<ul id="products-carousel" class="carousel">
<% #posts.select{ |post| post.categories.include?(#categories.find_by_name("Productos")) }.each do |post|%>
[...]
<% end %>
</ul>
</div>
[...]
<div class="modals">
<% #posts.select{ |post| post.categories.include?(#categories.find_by_name("Productos")) }.each do |post|%>
[...]
<% end %>
</div>
The problem here is that I'm using several database queries to perform this loop and I would like to re-use the first loop in other parts of this files in order to enhance performance.
For example I would like to do something like each do |post| do something in this first section, don't do nothing in this second section and continue in the third one. This way I could re-use the instance of the selected postd over which I'm iterating.
In your controller, you can do this:
#posts = Post.all
#productos_category = #categories.where(name: "Productos").first
#productos = #posts.where(category_id: #productos_category.id)
Note that I changed the way you find the associated #productos to use the ActiveRecord query interface, as opposed to using pure ruby select and include? methods. This will allow for the query to be much more efficient. I implied some things, such as the child key for the categories being category_id. Change this where appropriate.
EDIT 1
I believe this will work, although my experience with many-to-many relationships is somewhat limited:
#productos_category = #categories.where(name: "Productos").first
#productos_posts = Post.joins(:join_table).where(join_table: {category_id: #productos_category.id})
Where :join_table is the name of the table that is used in the has_many association. If it is a HABTM relationship, this will probably be called categories_posts.
Then your view would change to this:
<div class="list_carousel">
<ul id="products-carousel" class="carousel">
<% #productos_posts.each do |post|%>
[...]
<% end %>
</ul>
</div>
[...]
<div class="modals">
<% #productos_posts.each do |post|%>
[...]
<% end %>
</div>

Trying to break an array into three uneven arrays (Ruby on Rails)

Here's the code that will yield an array (I believe it's an array) of 13 page titles. I'd like to have titles 0-5 be in its own div, 6-8 in a second div and 9-12 in a third, for dropdown menus. I couldn't find this exact question/answer here.
<% #cms_site.pages.root.children.published.each. do |page| %>
<%= link_to page.label, page.full_path %>
<% end %>
Thank you!
What have you attempted? #each is not a very good use for this case. You might want to separate it into 3 different loops like so:
<% #cms_site.pages.root.children.published[0,5].each do |page| %>
<%= link_to page.label, page.full_path %>
<% end %>
<% #cms_site.pages.root.children.published[6,8].each do |page| %>
<%= link_to page.label, page.full_path %>
<% end %>
<% #cms_site.pages.root.children.published[9,12].each do |page| %>
<%= link_to page.label, page.full_path %>
<% end %>
EDIT
It seems like you're having some logic problems, it'd be wise for you to attempt it first at least.
The code up there should work but it's not really DRY and it can be extracted into maybe a helper method that uses the chapters for the iterator or possibly use a different iterator (e.g. each_with_index) and handle the check for each index in the block. There's many ways to go about doing what you asked.
Basically, if you're dealing with an array and you want to take the exact same elements from it each time, here's how to slice it:
# Your Array
elements = [1,2,3,4,5,6,7,8,9,10,11,12]
# This will give you three arrays inside one array. The first will be first six
# elements starting from 0, the second is 3 elements starting from 6, etc.
arrays = [ elements[0,6], elements[6,3], elements[9,3] ]
Now you can iterate through the array and reuse the code to generate the code you want.
arrays.each do |ar|
# Now render for each array as you please, and reuse the same code.
end

Rails- Index in form_for field names

I have a form that I am trying to build to edit multiple records. It's complicated, doesn't map straight to the database, and there can be any number of records. I have the code written so all of the data is passed to the view as a hash. Like this:
#formdata = {"datafield_1"=>"value_1", "datafield_2"=>"value_2"}
What I want to do is to create something like:
f.textfield :datafield_1
f.textfield :datafield_2
f.textfield :datafield_3
etc. etc. etc.
But I don't know how to pass the index of my for loop into the variable name. In short, how do I do :datafield_i where i is my index?
<% %w(1 2 3).each do |i| %>
<%= f.textfield(:"datafield_#{i}") -%>
<% end %>
or
<% #formdata.keys.each do |datafield| %>
<%= f.textfield(datafield.to_sym) -%>
<% end %>

Resources