Reduce transactions required for columns in other tables?

I have a simple application that keeps track of projects and tasks:

class Project < ActiveRecord::Base
  has_many :Tasks
end

class Task < ActiveRecord::Base
  belongs_to :Project
end

In a list view of tasks, I want to show the project name (and link it
to the action allowing the user to edit a project). Currently, that
logic is in the view (which may be my first mistake):

from app/view/task/list.rhtml:

<td><%= link_to Project.find(task.project_id).name, :controller =>
'Project', :action => 'edit', :id => task.project_id %></td>

But this causes the application to make two calls to the database to
get this information: one when the controller pulls its list of tasks:

from app/controller/task_controller.rb:
def list
  @task_pages, @tasks = paginate :tasks, :per_page => 10
end

and once when the Project.find() call is executed while parsing the
view. It would be far more efficient, from a database perspective, if
I only had to call on the database once to get the list of tasks.
Probably I could rewrite TaskController.list() to use Task.find() with
the best way to handle this situation? If so, then how do I paginate
the results?

Or is it better to just suck it up, and let Rails make an extra call
to the database for every record returned? It's not so bad when there
are fewer than 10 simultaneous users, and pagination keeps it to 10
tasks per page -- but that's still 11 database transactions per page
when it could just be 1.

Thoughts?

You need to move the find code out of your view and use eager loading in
your controller. Try this:

<td><%= link_to task.project.name, :controller =>'Project', :action =>
'edit', :id => task.project %></td>

def list
    @task_pages, @tasks = paginate :tasks, :include => :project,
:per_page => 10
end

-Bill

Z wrote:

That seems to have done the trick -- although I had to change the case
of "project" to "Project" to get it to work. Have I fouled up on a
case convention?

My database tables (MySQL on ext3, INNODB engine) are tasks and
projects. Models are Task and Project.

Maybe I'm being too nitpicky ... but I'm trying to learn and follow
the conventions.

Scott

I have a simple application that keeps track of projects and tasks:

class Project < ActiveRecord::Base
  has_many :Tasks

has_many :tasks # note the lowercase

end

class Task < ActiveRecord::Base
  belongs_to :Project

belongs_to :project # again, lowercase

end

In a list view of tasks, I want to show the project name (and link it
to the action allowing the user to edit a project). Currently, that
logic is in the view (which may be my first mistake):

from app/view/task/list.rhtml:

<td><%= link_to Project.find(task.project_id).name, :controller =>
'Project', :action => 'edit', :id => task.project_id %></td>

link_to task.project.name, :controller => 'project', :action => 'edit', :id => task.project_id

or learn how to use named routes and say:
link_to task.project.name, edit_project_path(task.project_id)

But this causes the application to make two calls to the database to
get this information: one when the controller pulls its list of tasks:

from app/controller/task_controller.rb:
def list
  @task_pages, @tasks = paginate :tasks, :per_page => 10

This is the perfect example of eager loading to avoid the 1+N problem:

   @task_pages, @tasks = paginate :tasks, :include => :project, :per_page => 10

end

and once when the Project.find() call is executed while parsing the
view. It would be far more efficient, from a database perspective, if
I only had to call on the database once to get the list of tasks.
Probably I could rewrite TaskController.list() to use Task.find() with
a :join option (pulling projects.name from the database), but is that
the best way to handle this situation? If so, then how do I paginate
the results?

Or is it better to just suck it up, and let Rails make an extra call
to the database for every record returned? It's not so bad when there
are fewer than 10 simultaneous users, and pagination keeps it to 10
tasks per page -- but that's still 11 database transactions per page
when it could just be 1.

Thoughts?

I think you need to spend a bit of time with a good book (like Agile Development with Rails, 2nd Ed.) or at least the online Rails API docs.

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com

Yes, in Ruby, anything starting with a capital letter is considered a
constant. I noticed that in your classes, but I assumed that was just
from you retyping it in your email. Your associations should be all
lower case. You are not being too picky :slight_smile:

`class Task < ActiveRecord::Base

belongs_to :project

end

class Task < ActiveRecord::Base

belongs_to :Project

end`

-Bill

Z wrote: