homeASCIIcasts

5: Using with_scope 

(view original Railscast)

Other translations: It Es Kr Fr

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