Using group_by today, trying to get my head around it and see if its the right solution for what I am trying to achieve. I have the following model
class Fixture < ActiveRecord::Base
attr_accessible :home_team, :away_team, :kickoff_time, :fixture_date
end
I want to group all the fixtures by fixture_date. So far my controller look like this
def fixturelist
#fixtures = Fixture.all
#fixture_date = #fixtures.group_by { |fd| fd.fixture_date }
end
What i would like to do then in my view is list the home_team and away team matches for that particular date
View
<% #fixture_date.each do |f| %>
<%= f %>
<% end %>
This outputs an array of all the fixtures by date, so group_by has worked. Im looking for some pointers to get this working correctly, ie see all fixtures listed for each date. seeing a working example should help me understand some more
Example
Date
Team 1 Vs Team2
Team 1 Vs Team2
Team 1 Vs Team2
Date 2
Team 1 Vs Team2
Team 1 Vs Team2
Team 1 Vs Team2
Thanks
Check this out,
http://railscasts.com/episodes/29-group-by-month
I think you will want your view code to look like this,
<% #fixture_date.sort.each do |date, fixtures| %>
<h2><%= date %></h2>
<% fixtures.each do |fixture| %>
<%= fixture.team_1 %> VS <%= fixture.team_2 %>
<% end %>
<% end %>
EDIT:
And if your fixture_date is a datetime column instead of just a date column, your controller code to look like this,
#fixture_date = #fixtures.group_by { |fd| fd.fixture_date.beginning_of_day }
Related
I have 2 Models in my application. Project & Note. A project has_many notes. This all works great but on the projects index page.html.erb I would like to show the last note for a project.
My question is how do I retrieve this and then display it, on the index screen?
You can get the last note using project.notes.last. In your view, add below :
<% projects.each do |project| %>
<% last_note = project.notes.last %>
<%= last_note.note unless last_note.nil? %> # get last note per project if it exists
<% end %>
I am working with a Calendar and I think that calendar deals only with date without a time.
Note: requested_date is a DateTime Attribute. I want to get all reservations with requested date and covert it to date only:
users_controller.rb
def myprofile
#reservation = Reservation.all
#resv_by_date = #reservation.group_by(&:requested_date) <-- make requested_date to date only
end
myprofile.html.erb
<div id="admin">
<%= calendar do |date| %>
<%= date.day %><br>
<% #resv_by_date.each do |reservation| %>
<%= reservation.requested_date.to_date %><br>
<% end %>
<% end %>
</div>
(this month 'May') requested_date is existing on my database
image output after the solution of the 1st answer
I don't think you want to use a group on your ActiveRecord relation not group_by which is a Ruby method.
Also, the method to get a Date from a DateTime object is datetime.to_date:
#reservations_by_date = Reservation.select(:requested_date).group(:requested_date)
#reservations_by_date.each { |reservation| puts reservation.requested_date.to_date }
Normally I'd advice you to try to group the data in the DB already (using group) for performance reasons instead of ruby code (group_by). But in your specific case it seems that you indeed need to retrieve all reservations in the given time period (e.g. month) and just group them by the date so that you can display all of them in the calendar view. In that case, you indeed have to group in ruby code.
You can do that simply by updating the block in group_by:
#reservations_by_date = Reservation.all.group_by { |res| res.requested_date.to_date }
Note that most probably you'll want to narrow down the select only to the given time period (e.g. the displayed month) first, using where conditions, I skipped that part from this answer.
The grouping above will create a hash of the reservations where the keys will be the dates (not datetimes) and the values will be arrays of reservations in the given date. In the calendar view, you can simply browse once you've accessed them using the date key:
<% calendar do |date| %>
<%= date.day %><br>
<% #reservations_by_date[date].each do |reservation| %>
<%= reservation.name ... or whatever %><br>
<% end %>
In a Rails 3.2 app I have a model Project, which has many Tasks. Each Task has a :status field, which is an integer as follows
1=Normal
2=Urgent
In the Project show view, I want to display a text alert if any of the associated tasks are flagged as urgent.
If the status field was within the Project model, I would do something like this:
<% if Project.status == 2 %>
<div class="alert">URGENT TASKS!</div>
<% end %>
How can I set up a similar if statement, that will cycle through all associated Tasks, and return true if at least one task is marked as urgent?
I'm not sure what terms I should be searching on for this sort of functionality. Or maybe I'm not looking at the problem the right way. I'd be grateful for any pointers in the right direction.
Thanks
This method in Project will do it:
def urgent?
tasks.detect{|t| t.status==2}
end
Then you can do, if you have #project set to the project you're looking at:
<% if #project.urgent? %>
...whatever ...
<% end %>
This next bit was added in answer to your comment. This method in Project will return the highest priority set (lowest number in your example) for any task in a particular project:
def highest_priority
tasks.map{|t| t.status}.min
end
You can then switch between them in your view:
<% case #project.highest_priority
when 1 %>
...priority 1 stuff...
<% when 2 %>
...priority 2 stuff...
<% when 3 %>
...and so on...
<% end %>
I guess that you want to check if a project has some urgent task to be completed. If thats the case I think the best way to achieve that would be to create new method in the Project model, something like this:
def has_urgent_task?
tasks.map(&:status).include?(Task::URGENT)
end
Assuming you have defined your statuses as constants in your Task model, if not just replace Task::URGENT for 2.
So in your view you only need to do this:
<% if #project.has_urgent_task? %>
<div class="alert">URGENT TASKS!</div>
<% end %>
I'm a noob trying to build up my first rails app. It's a "betting game" where users try to predict football results and get points for correct result or correct "tendency" (win, draw, loose).
Creating and updating bets is working fine, also creating games and inserting results as an admin user. But I'm having problems in displaying all bets from all users for each game in a kind of an index page, which should roughly look like this:
| User1 | User2 | User3 ...
Game Result | Bet | Bet | Bet
Team1 : Team2 1:0 | 1:1 | 3:2 | 1:0
Team3 : Team4 1:2 | 1:2 | -:- | 3:0
Team5 : Team6 -:- | 1:2 | -:- | 3:0
...
My Model structure looks like this:
class User < ActiveRecord::Base
has_many :bets
class Game < ActiveRecord::Base
has_many :bets
class Bet < ActiveRecord::Base
belongs_to :user, :class_name => 'User', :foreign_key => 'user_id'
belongs_to :game, :class_name => 'Game', :foreign_key => 'game_id'
Indicated by the -:- in the above scetch, not every user will have placed a bet on every game, and not every game will have a result.
I tried a thousand ways of getting the data together for the index view and got issues with multiple errors (nil object, no method etc.). The current (not working) approach is getting everything in the controller:
def index
#users = User.all
#games = Game.all
#bets = Bet.all
end
and in the view trying to iterate to the games and within each games through the users and bets in the view, while checking if a bet of a user and a game exists, which leads to unreadable messy code there:
<% #games.each do |game| %>
<tr>
<td><%= game.home_team %> - <%= game.away_team %></td>
<td>
<% if game.away_score.nil? %>
-:-
<% else %>
<%= game.home_score %> : <%= game.away_score %>
<% end -%>
</td>
<% #users.each do |user| %>
<% bet = Bet.where( :user_id => user.id, :game_id => game.id) %>
<% if bet.exists? %>
<td><%= bet.home_bet %> : <%= bet.away_bet %></td>
<% else %>
<td>-:-</td>
<% end -%>
<% end -%>
</tr>
<% end -%>
I hope you can suggest a cleaner way to accomplish this. Unfortunately, none of the dozens of posts I read could solve my problem.
So, the first question is: what is the best way to retrieve the needed data from the different tables? Corresponding second Question: Is it best to build the data in the controller and pass it to the view or put it all together in the view?
I'm using rails 3.1.1 with squlite3.
I hope, someone can help this stupid newbee...
So many issues here... let's start
there's no need to iterate through ALL users for EACH game. You can iterate through game.bets and for each 'bet' get a user by bet.user, according to the relationship you have built
To answer your 1st question: since you are trying to make a 'report' kind of a view with an intent to show 'all' games, your approach to have #games = Game.all is right. You don't need 2 other .all collections though since you can infer the data from the relationships
2nd question: In Rails it is considered a good approach to have 'fat models, skinny controllers' which means that your data crunching/logic code should be in a model and controller should have only code used by the correspondent views.
About your view: In your case your view is not terribly bad since you have a sparsely populated tables and you should use ifs for cases where score is not available etc
I would probably do something like this:
controller:
#users = User.all
#game_bets = Game.all.map { |game| [game, game.bets.index_by(&:user)] }
view:
<% #game_bets.each do |game, bets| %>
...
<% #users.each do |user| %>
<% if bets.has_key?(user) %>
<td><%= bets[user].home_bet %></td>
<% else %>
<td>-:-</td>
...
I have a books model with a date type column named publish_date. On my views I'm iterating through the books and I want to group the books by year such that I have a heading for every year and books that were published on that year to be listed below the year heading.
So by starting with "2010" all books published on 2010 would be listed, then another heading "2009" with all books published in 2009 listed below it and so forth.
<% #all_books.each do |book| %>
<%=link_to book.title + ", (PDF, " + get_file_size(book.size) + ")" %>
<% end %>
By doing a book.publish_date.strftime("%Y") I am able to get the year but I do not know how to group the entries by year. Any help on this would be appreciated.
You can use group_by (see API) like (of the top of my head
<% #all_books.group_by(&:year).each do |year, book| %>
...
<% end %>
def year
self.created_at.strftime('%Y')
end
< % #all_books.group_by(&:year).each do |year, book| %>
Year < %= year %>
# render books here
< % end %>
What say?
You can use group_by for convenience, but your need can be better served by relying on DB for sorting and a each loop. This avoids the cost of client side sorting and hash manipulations for grouping.
Somewhere in your controller
#all_books = Book.all(:order => "publish_date DESC")
In your view
<%year = nil
#all_books.each do |book|
if year.nil? or year > book.publish_date.year
year = book.publish_date.year
%>
<h1> <%=year%><h1>
<%end % >
<%=link_to book.title + ", (PDF, " + get_file_size(book.size) + ")" %>
<%end %>
The quick and dirty approach is to simply group_by the year and iterate over those:
#all_books.group_by { |b| b.created_at.year }.each do |year, books|
# All books for one year, so put heading here
books.each do |book|
# ...
end
end
This requires sorting within the Rails application, so you will need to retrieve all relevant records in order to have the data properly organized. To do the sort on the server you will probably need to introduce a year column and keep it in sync with the created_at time.