Rails group_by and in_groups_of error - ruby-on-rails-3

I have a list of organisations, grouped and displayed by their name, in alphabetical order. I want to display these across 4 columns for each letter, i.e.:
A
A... A... A... A...
A... A... A... A...
...
Z
Z... Z...
I have used the following code:
<% #organisations.keys.sort.each do |starting_letter| %>
<div class="page-chunk default">
<h6><%= starting_letter %></h6>
<% #organisations[starting_letter].each do |organisations| %>
<% organisations.in_groups_of(4).each do |column| %>
<div class="one_quarter">
<% column.each do |organisation| %>
<%= link_to organisation.name, organisation_path(organisation) %><br />
<% end %>
</div>
<% end %>
<% end %>
</div>
<% end %>
And in the controller:
#organisations = Organisation.all.group_by{ |org| org.name[0] }
But get undefined methodin_groups_of' for #for my troubles. If I change the code to#organisations[starting_letter].in_groups_of(4).each do |organisations|then I get aNilClass` error.
What have I done wrong and how should I fix it?

Try organisations.in_groups_of(4, false)
Without the false, it will fill in any empty spots in the last group with nils, which means it will try to call name on nil.

Related

Rails. How to get stat column from votes table where user_id = current user

I have petition site. I building now the voting system, but thats don't work glad.
To create only one vote per user I use this condition in view:
<% if #post.votes.where(user_id: current_user.id).blank? %>
It's return true if user do not vote for current post.
But when i want to show user vote statement with this code:
<% if #post.votes(user_id: current_user.id) == 1 %>
"u voted LIKE"
<% else %>
"u voted DISLIKE"
<% end %>
it return me the error: We're sorry, but something went wrong (500)
I'm in development mode. Thanks.
You are missing where and count in the statement.
try this,
<% if #post.votes.where(user_id: current_user.id).count.eql?(1) %>
"u voted LIKE"
<% else %>
"u voted DISLIKE"
<% end %>
Update the condition as
<% if #post.votes(user_id: current_user.id).count == 1 %>
"u voted"
<% else %>
"u dont voted"
<% end %>
You are counting the votes for that post of the user as 1 , if it is 1 then he has voted. else not voted.

Grouping in Rails with Group Headline

I'd like to group a collection alphabetically by title:
#projects = Project.find_all_by_user_id(current_user.id)
The view should contain a list of projects grouped by title, e.g.:
A
Andre's Project
Ananas
C
Chemnitz
Cleopatra
F
Find a new office
S
Super secret stuff
But I got no clue how to do this in rails. Does rails provide a functionality to do this or do I need to write my own loop looking for the titles etc.?
Thank you!
Not Rails but Ruby does the trick. In your view:
<% #projects.group_by{ |project| project.name[0].downcase }.each do |letter, projects| %>
<div id="letter-<%= letter %>" class="letter-group">
<h2><%= letter.upcase %><h2>
<% projects.each do |project| %>
<p><%= link_to project.name, project %></p>
<% end %>
</div>
<% end %>
group_by (ruby-doc) returns a hash you can easily loop through with letters as keys and arrays of corresponding projects as values. Be sure to already get your records sorted by project's name: (in your controller)
#projects = Project.order("name ASC").find_all_by_user_id(current_user.id)

Grouping records within a view in Rails 3?

I have the following code in my Rails 3 application:
Show view (from another model called animal.rb)
<% #animal.labs.each do |lab| %>
<li>
<%= lab.TestDone.strftime("%d %b. %Y") %>
<h5><%= lab.TestType %></h5>
<h6><%= lab.TestLower %></h6>
<b><%= lab.TestResult %></b>
<h6><%= lab.TestUpper %></h6>
</li>
<% end %>
lab model
belongs_to :animal
default_scope :order => "TestDone DESC", :group => "TestDone"
The above code successfully group all results by date. However, it only shows the first of each value after the date.
For example, if the output was originally (before the grouping) like this:
<li>
26 April 2012
<h5>Glucose</h5>
<h6>1.0</h6>
<b>1.8</b>
<h6>2.0</h6>
</li>
<li>
26 April 2012
<h5>WBC</h5>
<h6>1.1</h6>
<b>2.8</b>
<h6>3.0</h6>
</li>
<li>
26 April 2012
<h5>ABC</h5>
<h6>1.0</h6>
<b>1.6</b>
<h6>2.0</h6>
</li>
then it would output the following after the grouping:
<li>
26 April 2012
<h5>Glucose</h5>
<h6>1.0</h6>
<b>1.8</b>
<h6>2.0</h6>
</li>
What is the correct way of producing something like this:
<li>26 April 2012</li>
<li>
<h5>Glucose</h5>
<h6>1.0</h6>
<b>1.8</b>
<h6>2.0</h6>
</li>
<li>
<h5>WBC</h5>
<h6>1.1</h6>
<b>2.8</b>
<h6>3.0</h6>
</li>
<li>
<h5>ABC</h5>
<h6>1.0</h6>
<b>1.6</b>
<h6>2.0</h6>
</li>
So I have a date heading and then every record with that date is listed below?
A simpler way would be to use group_by like so:
<% #animal.labs.group_by{|l| l.TestDone.strftime("%d %b. %Y") }.each do |testdate,labs| %>
<li><%= testdate %></li>
<% labs.each do |lab| %>
<li>
<h5><%= lab.TestType %></h5>
<h6><%= lab.TestLower %></h6>
<b><%= lab.TestResult %></b>
<h6><%= lab.TestUpper %></h6>
</li>
<% end %>
<% end %>
http://api.rubyonrails.org/classes/Enumerable.html#method-i-group_by
Grouping not works the way you want to use it. First, yo ushould not group it in your default_scope, but you may use some aggreagation in the view, or in the controller.
Model:
default_scope :order => "TestDone DESC"
View:
<% prev = nil %>
<% #animal.labs.each do |lab| %>
<%= "</ul></li>" if prev != nil && prev != lab.TestDone %>
<%= "<li>"+lab.TestDone.strftime("%d %b. %Y")+"<ul>" if prev != lab.TestDone %>
<li>
<h5><%= lab.TestType %></h5>
<h6><%= lab.TestLower %></h6>
<b><%= lab.TestResult %></b>
<h6><%= lab.TestUpper %></h6>
</li>
<% prev = lab.TestDone %>
<% end %>
<%= "</ul></li>" if prev != nil %>
Not the most pretty solution, but it is based on your code.
Basically you need to store the last element's date, in order to compare it with the actual element's date. If they differ, then the new date must be shown. Because they ordered by date, the elements with the same date are close to each other.
I think that is what you was looking for.

Rails 3 displaying count inside a loop

The following displays a list of documents grouped by subject and the name of each document is the name of the packet type. How do I display the the count for each packet type name? so for example if there are two documents for the first subject and their packet type names are 'class' how do I display 'class 1 of 2' and class 2 of 2' next to the packet type name?
controller:
class DevelopController < ApplicationController
def index
list
render('list')
end
def list
#subjects = Subject.includes(:documents => :packet_type)
end
end
view:
<ol>
<% #subjects.each do |subject| %>
<li><%= subject.subject_name %>
<ul>
<% subject.documents.each do |document| %>
<li><%= document.packet_type.name %></li>
</li>
<% end %>
</ul>
<% end %>
</ol>
You can get the total count with .size or .count. To get the current index, you can use each_with_index instead of each. And here on a silver plate : http://apidock.com/ruby/Enumerable/each_with_index :)

need to create a helper for rails 3

I need to create some type of helper for a form where it will create a select for each day of the week.
Below, creates the 5 instances, but only submits the last one.
def basic_question(q)
a = ""
5.times do
a << select("question[question_id_#{q.id}]", :response, (0..30).to_a) + " for #{q.survey.publish_on.strftime('%A')} #{q.survey.publish_on.strftime('%D')} <br />"
end
return a.html_safe
end
EDIT
Here is the view to take the survey
<%= form_for store_survey_path(#survey) do |f| %>
<% hidden_field.user_id, :value => current_user.id %>
<% #survey.questions.each do |q| %>
<li><%= q.content %></li>
<%= question_helper(q) %>
<% end %>
<p><%= f.submit %></p>
<% end %>
And the helper that checks for the type of question it is.
def question_helper(question)
case question.question_type
when 'basic'
return basic_question(question)
when 'fill_in'
return fill_in_question(question)
when 'scale_5'
return "should return a scale of 5"
when 'scale_10'
return "should return a scale of 10"
when 'must_choose_answer'
return question.answers.to_s
when 'just_label'
return " I will be a label"
else
return "Couldn't find in helper"
end
end
You could either go with giving the separate selects different names so that they are submitted separately, or you could submit them all as an array. I would go with the last option.
To submit them as an array, you have to add [] to the end of the select name like this:
question[question_id_#{q.id}][]
Which would end up looking like this:
a << select("question[question_id_#{q.id}][]", :response, (0..30).to_a) + " for #{q.survey.publish_on.strftime('%A')} #{q.survey.publish_on.strftime('%D')} <br />"
I hope that helps.