Search code examples
ruby-on-railsnamed-scope

Keeping named_scope Extensions DRY


In Rails, you can add a block after a named_scope for additional, context-sensitive methods like so:

class User < ActiveRecord::Base
  named_scope :inactive, :conditions => {:active => false} do
    def activate
      each { |i| i.update_attribute(:active, true) }
    end
  end
end

In this example, the activate method is being defined not on the User class, but on the ActiveRecord::NamedScope::Scope object.

I have a series of three scopes that need to have identical method definitions. In the interests of not repeating code, how would I abstract that block such that I could define it once and pass it to each named_scope?


Solution

  • Firstly, great question--I didn't know about that feature of named scopes! The following works for me:

    class User < ActiveRecord::Base
      add_activate = lambda do
        define_method "activate" do
          each { |i| i.update_attribute(:active, true) }
        end
      end
    
      named_scope :inactive, :conditions => {:active => false}, &add_activate
    end
    

    You can pass the add_activate block as the last argument to any named scopes that need the activate method.