Reputation: 2247
I have a User
, List
, and Task
models.
A task belongs_to
user and list, a list has_many
tasks and belongs_to
user, and a user has_many
list and has_many
tasks.
I have part of what I want to display working in my index view, with just one snafu that I am getting hung up on.
I'm able to display the first created task in the index view of all the lists. The problem is, the first task created is displayed for all of the lists, even if the list is NOT associated with the task.
In the list index view I want the first task created to display only if it is associated with the list.
Task model:
class Task < ActiveRecord::Base
attr_accessible :completed, :description, :list_id, :user_id
belongs_to :list
belongs_to :user
scope :completed, where(:completed => true)
scope :incomplete, where(:completed => false)
def self.most_recent
first(:order => 'id ASC' ) # or whatever query you need to get the most recent
end
end
List Index View-
<div class="span12 offset2">
<% @lists.each do |list| %>
<div class="well row span4">
<div class="span3">
</div>
<div class="span4">
<span class="lead">
<%= link_to "#{list.name}", list_url(list) %>
</span>
<p>
<%= list.description %>
</p><hr>
<div class="pull-right" id="gage-<%= list.id %>" style="width:170px; height:100px;"></div>
<br>
<span class="offset1">
<% if Task.most_recent %>
<span class="pull-left"> <%= image_tag Task.most_recent.user.gravatar_url, :class => "gravatar_index" %></span>
<% end %>
</span>
</div>
<% end %>
</div>
I'm still new to rails but I know I'm very close. What am I overlooking here? emphasized text
===========
I've tested @Baldrick's solution and now seem to be getting another error
My view with described solution-
<% if Task.most_recent(list) %>
<span class="pull-left"> <%= image_tag Task.most_recent.user.gravatar_url, :class => "gravatar_index" %></span>
<% end %>
I am now getting the error-
SQLite3::SQLException: no such column: tasks.list: SELECT "tasks".* FROM "tasks" WHERE "tasks"."list" = 4 ORDER BY id ASC LIMIT 1
I must not be understanding correctly because I have such a created column when I created the Task model
class CreateTasks < ActiveRecord::Migration
def change
create_table :tasks do |t|
t.string :description
t.boolean :completed, :default => false
t.integer :list_id
t.timestamps
end
end
end
Is this a case where I need to add an index to be able to make my query?
Upvotes: 1
Views: 731
Reputation: 24350
The method most_recent
gives you the last create task of all tasks. What you wnat is the most recent task of a given list.
You should give a parameter to the list
def self.most_recent(list)
where(list_id: list.id).order('id ASC').first # or whatever query you need to get the most recent
end
Upvotes: 2
Reputation: 18627
Based on your description, it does not sound like you want, for each list, to show the most recent task for that list. Rather, it seems you want to have the overall most recent task to appear multiple times, once for each list that happens to contain it. To achieve this you want to replace if Task.most_recent
with if list.tasks.include? Task.most_recent
.
---EDIT---
Okay, if you actually want to show, for each list, that list's most recent task, then you should be going about this fairly differently. In your List
class you should have the following method:
def most_recent_task
tasks.first(:order => 'id ASC') # or whatever
end
Then in your view you'll replace both occurrences of Task.most_recent
with list.most_recent_task
. And if your lists will always have at least one task, then you can get rid of the guard clause (i.e. the if
) altogether.
As a further refactor you may want to take some computation out of the view, and create "presenters" for your lists index, which would just be an array of presenters for each individual list. An individual presenter should be a plain object with the information you need about the list, precomputed:
Upvotes: 0
Reputation: 4230
Your most_recent
method returns the first task of Task. There is nothing in this method tying the task to any list. You'd need to pass the list_id to this method to get the first task for this list, e.g.
def self.most_recent(list_id)
first(:order => 'id ASC', :list_id => list_id)
end
Edit: other solution didn't work.
Upvotes: 1