homeASCIIcasts

3: Find Through Association 

(view original Railscast)

Other translations: It Es Fr

In this Rails application we have a Project model which has_many tasks:

class Project < ActiveRecord::Base
    has_many :tasks
end

and a Task model which belongs_to a project:

class Task < ActiveRecord::Base
    belongs_to :project
end

In the project’s controller method is a show action. We want to display a Project, along with all of the Tasks in the project which are incomplete. To do this we perform a find on the Task model to find tasks where the project_id matches the Project’s id and where the complete field is false:

class ProjectsController < ApplicationController
    def show
        @project = Project.find(params[:id])
        @tasks = Task.find(:all, :conditions => ['project_id = ? AND complete = ?', @project.id, false])
    end
end

There is a better way to do this. A find can be performed through an association. The line above that finds that tasks can be changed from

@tasks = Task.find(:all, :conditions => ['project_id = ? AND complete = ?', @project.id, false])

to

@tasks = @project.tasks.find(:all, :conditions => [complete = ?', false])

This means that the project_id can be removed from the find as it’s already specified by doing the find through the project’s tasks.

This line can be shortened even more by using a dynamic find method in the scope of the project model to this:

@tasks = @project.tasks.find_all_by_complete(false)