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.
Related
I am trying to create an advanced search form for a rails blog
I'm trying to avoid using a gem
I have a table posts with a title, location_id and category_id, the last two are connected to two tables Location (:small, :greater) and Category (name), but I doubt that's important for this question
I have a search form which finds all posts where location_id and category_id is equal to the user set option
<%= form_for(#advanced_search) do |f| %>
<div class="field">
<%= f.label :category_search %><br>
<%= f.collection_select :category_search, Category.all, :id, :name, :
include_blank => "any category" %>
</div>
<div class="field">
<%= f.label :location_search %><br>
<%= f.collection_select :location_search, Location.all, :id, :locationsmallgreat
,:include_blank => "any city" %>
<%= f.submit %>
<% end %>
Once again i doubt that's important for the question which is probably simpler than I'm explaining it to be
Basically I have this so far
#posts = Post.all
#posts = #posts.where('category_id = ?', #advanced_search.category_search) if #advanced_search.category_search != "any category"
#posts = #posts.where('location_id = ?', #advanced_search.location_search) if #advanced_search.location_search != "any city"
But it doesn't seem to work
I need it to work as so, If the form has Category = Any category (:included_blank => "any category)
and Location = London
It would search for all Posts where location is == london, BUT it would remove the .where for the category, seeing that it is == any city and vice versa if a Category was selected and Location was left blank (:included_blank => "any city)
Thanks
if #advanced_search.category_search.present? && #advanced_search.location_search.present?
Post.
where('category_id = ?', #advanced_search.category_search).
where('location_id = ?', #advanced_search.location_search).
all
elsif #advanced_search.category_search.present?
Post.
where('category_id = ?', #advanced_search.category_search).
all
elsif #advanced_search.location_search.present?
Post.
where('location_id = ?', #advanced_search.location_search).
all
else
Post.all
end
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)
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.
I am trying to email a monthly report which is simple the current month's income compared to the last months.
I have all of that working in my report controller (which references another model called Clinical):
# Clinical income by month report
#clinical_income_by_month = Clinical.select(%q{date_format(transactiondate, '%Y') as year, date_format(transactiondate, '%M') as month, sum(LineBalance) as income})
.where(:payments => 0)
.where('linebalance <> ?', 0)
.where('analysiscode <> ?', 213)
.group(:monthyear)
I then have a partial for the table with the data:
<div class="row">
<div class="twelve columns"><h5>This months income so far is <span style="font-size:1.2em"class="<% if #clinical_income_by_month.first.income >= #clinical_income_by_month.first(:offset => 12).income %>green<% else %>red<% end %> radius label"><%= number_to_currency(#clinical_income_by_month.first.income, :unit => "£", :separator => ".", :delimiter => ",") %></span></h5> <%= #clinical_income_by_month.first.month %> <%= #clinical_income_by_month.first(:offset => 12).year %>'s income was <%= number_to_currency(#clinical_income_by_month.first(:offset => 12).income, :unit => "£", :separator => ".", :delimiter => ",") %>.</div>
</div>
<hr />
<table>
<tr>
<th>Year</th>
<th>Month</th>
<th>Income</th>
</tr>
<% #clinical_income_by_month.each do |c| %>
<tr>
<td><%= c.year %></td>
<td><%= c.month %></td>
<td><%= number_to_currency(c.income, :unit => "£", :separator => ".", :delimiter => ",") %></td>
</tr>
<% end %>
</table>
I would like to be able to pull that partial into my email, or if that's not possible, I would like to show the value of the last income.
<%= #clinical_income_by_month.first.income %>
My email code looks like this:
Finance Report
================================================
<%= number_to_currency(#clinical_income_by_month.first.income) %>
The error I am getting is:
1.9.2-p318 :009 > UserMailer.finance_report().deliver
ActionView::Template::Error: undefined method `first' for nil:NilClass
from /Users/dannymcclelland/Projects/premvet/app/views/user_mailer/finance_report.text.erb:3:in `_app_views_user_mailer_finance_report_text_erb___4501411113534248604_70358523362460'
It works when I pull a value from the standard method:
<%= number_to_currency(Clinical.first.UserID) %>
but not when I call it from the #clinical_income_by_month report I created.
Any pointers would be appreciated!
You need to do something like this:
in user_mailer.rb
def finance_report(clinical_income_by_month)
#clinical_income_by_month = clinical_income_by_month
... # all you had here before
end
And in the controller call it this way:
UserMailer.finance_report(#clinical_income_by_month).deliver
Clearly your #clinical_income_by_month is nil. That means the select query is not returning values as you think it should. This is a model problem. Instead of checking the views, you should fire up the "rails console" and see whether the query returns the values you want.
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 :)