Plugins - scope_out

StarAdd to favorites

ScopeOut

Author:John Andrews
License:Distributes under the same terms as Ruby
======

Usage:

  class Person < ActiveRecord::Base
    scope_out :women, :conditions => ["people.sex = ?", "F"]
  end

The above code creates three class methods: find_women, with_women, and calculate_women. It is equivalent to doing the following:

  class Person < ActiveRecord::Base
    def Person.with_women
      with_scope :find => {:conditions => ['people.sex => ?', "F"]} do
        yield
      end
    end

    def Person.find_women(*args)
      with_women {find(*args)}
    end

    def Person.calculate_women(*args)
      with_women {calculate(*args)}
    end
  end

with_x

Person.with_women acts just like with_scope, except the scope is already defined. For example:

  Person.with_women do
    Person.find(:all, :order => 'people.age desc')
  end

find_x

Person.find_women acts just like find, except that it is scoped with with_women:

  Person.calculate_women(:first, :include => :pets)
  # equivalent to Person.find(:first, :conditions => ["people.sex = ?", "F"], :include => :pets)

calculate_x

Person.calculate_active (you guessed it) is exactly like Person.calculate, but scoped with ‘with_women’

  Person.calculate_active(:count, :all)
  # is the same as Person.calculate(:count, :all, :conditions => ["person.sex = ?", "F"])

Association Finders

scope_out also creates a module called AssociationMethods inside the class that defines the scope. Using this, you can extend your associations using the same scopes. Let’s define a second class:

  class Person < ActiveRecord::Base
    has_many :pets, :extend => Pet::AssociationMethods
    scope_out :women, :conditions => ["people.sex = ?", "F"]
  end

  class Pet < ActiveRecord::Base
    belongs_to :person
    scope_out :cats, :conditions => ["pets.type = ?", "Feline"]
  end

  woman = Person.find_women(:first)
  her_pets = woman.pets
  her_cats = woman.pets.cats

  # cats is cached on the association, so this doesn't cause another call to the database
  # unless you do woman.pets.cats(:reload)
  puts "Cat Lady!" if woman.pets.cats.length > 4

Flexible Syntax

All of the following define the same scope:

  class Ticket
    scope_out :active
    scope_out :active, :field => 'active', :value => true
    scope_out :active, :conditions => ["active = ?", true]
    scope_out :active, :conditions => {:active => true} # rails >= 1.2
  end

If you want to use a dynamic condition (which will be evaluated each time the scope is called), you can pass the options hash as a block.

  class Person < ActiveRecord::Base
    scope_out :adults do
      {:conditions => ["people.birthdate < ?", 18.years.ago],
       :order => 'people.birthdate asc' }
    end
  end

John Andrews

http://code.google.com/p/scope-out-rails

http://scope-out-rails.googlecode.com/svn/trunk/

Rails' (MIT)

  • Currently 4.9/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Model

Tags

Comments

Add a comment
Tim Watson 2 Dec 2007

scope_out through association possible?

I love scope_out, its a life saver, but is it possible to do something like?

ModelA.find(:all, :include => :model_b.active)

Where active is a scope_out defined in ModelB ?

andy 2 Nov 2007
This plugin seems to have a problem with the :group option for find. ArgumentError (Unknown key(s): group): /var/lib/gems/1.8/gems/activesupport-1.4.4/lib/active_support/core_ext/hash/keys.rb:48:in `assert_valid_keys'
John Andrews 7 Feb 2007

UPDATE: If you want to use a dynamic condition (which will be evaluated each time the scope is called), you can pass the options hash as a block. Please see the description above under the heading "Flexible Syntax" for an example.

John Andrews 17 Jan 2007

Keith, Current implementation would evaluate it once at class definition time. I'm working on a way to make this dynamic. I'll post an update as soon as I get this worked out.

keith 17 Jan 2007

Neat idea.

One question:

Does the macro scope_out, or more specifically, the parameters given to the macro, get run at "run time" or at class definition time?

To shed some more light on my question, consider the following example:

scope_out :yesterday, :conditions =&gt; ['shown_at &gt;= :yesterday and shown_at &lt; :today', {:yesterday =&gt; (Date.today-1), :today =&gt; Date.today}]

Does the code Date.today get run once as the class is defined, ot will it get run every time I use MyClass.find_yesterday(:all)

Search Plugins

Query syntax

Plugins by Category

Sponsors

Rails Kits: Get Code. Get Moving.

Have a comment?