---
title: pure class
teaser:
tags: web,rails
author: Jared Carroll
published_on: 2007-07-17
---

Specifying your domain model associations in Rails is all done in Ruby and looks
nice.

Say in this app users can write reviews (it doesn't matter what they're
reviewing, but we could say music):

```ruby
class User < ActiveRecord::Base

  has_many :reviews

end

class Review < ActiveRecord::Base

  belongs_to :user

end
```

Now `#has_many` and `#belongs_to` are class methods available on
`ActiveRecord::Base` subclasses that generate some instance methods for the
subclass that provide support for the association.

I want a method on my `User`'s `reviews` association that gives me all a
`User`'s `Review` s that have a rating of 'good'.  Something like:

```ruby
user.reviews.good
```

There's a couple ways I can do this:

You can pass a block to #has_many:

```ruby
class User < ActiveRecord::Base

  has_many :reviews do

    def good
      find :all,
        :conditions => ['rating = ?', Review::GOOD]
    end

  end

end

class Review < ActiveRecord::Base

  POOR, AVERAGE, GOOD = 0, 1, 2

  belongs_to :user

end
```

I'm not a huge fan of this because its syntactically ugly.

You can also put the extensions in a separate module and file and specify the
module name as a parameter in the #has_many call:

```ruby
module UserExtensions

  def good
    find :all,
      :conditions => ['rating = ?', Review::GOOD]
  end

end

class User < ActiveRecord::Base

  has_many :reviews, :extend => UserExtensions

end

class Review < ActiveRecord::Base

  POOR, AVERAGE, GOOD = 0, 1, 2

  belongs_to :user

end
```

This is syntactically cleaner but now your `User` model behavior is spread over
2 files, since I put the module in a separate file in say
(`lib/user_extensions.rb`).

Those 2 techniques are well documented and known.  However, this 3rd one I've
run into accidentally.

Define the extensions as class methods on the associated class:

```ruby
class User < ActiveRecord::Base

  has_many :reviews

end

class Review < ActiveRecord::Base

  POOR, AVERAGE, GOOD = 0, 1, 2

  belongs_to :user

  def self.good
    find :all,
      :conditions => ['rating = ?', Review::GOOD]
  end

end
```

Apparently what happens is that `ActiveRecord` wraps that call to `Review#good`
in a block that's passed to `ActiveRecord::Base#with_scope` in order to find
only `Review` s for a specific `User`.

Something along the lines of:

```ruby
User.with_scope(:find => { :conditions => ['user_id = ?', id] }) do
  Review.good
end
```

I'm not a fan of this 3rd way because I don't like seeing a class method on
`Review` that's never directly called.  It's only indirectly called through a
`User`'s `Review` association.
