In this episode we’ll talk about with_scope. Below is a Task model that has a class method that returns all of the incomplete tasks.
class Task < ActiveRecord::Base
belongs_to :project
def self.find_incomplete
find_all_by_complete(false, :order => 'created_at DESC')
end
end
This method is used in the TasksController.
class TasksController < ApplicationController
def index
@tasks = Task.find_incomplete
end
This is a little limiting as we can’t add conditions to the custom find method to find, say, the first twenty incomplete tasks. What we want to do is something like
@tasks = Task.find_incomplete :limit => 20
One way to do this is to add an options hash to the find_incomplete method in the model and merge it with the options in the find, but a more elegant solution exists with find_scope, passing the find options.
class Task < ActiveRecord::Base
belongs_to :project
def self.find_incomplete(options = {})
with_scope :find => options do
find_all_by_complete(false, :order => 'created_at DESC')
end
end
end
Any find executed within the with_scope block will automatically inherit the specified options. Now the find_incomplete can take any conditions passed. This will also work within another scope. Our custom method is called in the ProjectsController. We can pass a limit condition here as well. This find passes through two scopes: first the incomplete tasks are found within the scope of the specified project and secondly they are limited to the first twenty.
@tasks = @project.tasks.find_incomplete :limit => 20