Rails: Is that possible to define named scope in a module?
Asked Answered
C

3

29

Say there are 3 models: A, B, and C. Each of these models has the x attribute.

Is that possible to define a named scope in a module and include this module in A, B, and C ?

I tried to do so and got an error message saying that scope is not recognized...

Carolinian answered 15/1, 2011 at 11:34 Comment(0)
W
52

Yes it is

module Foo
  def self.included(base)
    base.class_eval do
      scope :your_scope, lambda {}
    end
  end
end
Waler answered 15/1, 2011 at 11:37 Comment(2)
Can validation and relationship be defined this way?Lathy
Can't say 100%, but I can't think why not.Waler
K
33

As of Rails 3.1 the syntax is simplified a little by ActiveSupport::Concern:

Now you can do

require 'active_support/concern'

module M
  extend ActiveSupport::Concern

  included do
    scope :disabled, where(:disabled => true)
  end

  module ClassMethods
   ...
  end
end

ActiveSupport::Concern also sweeps in the dependencies of the included module, here is the documentation

[update, addressing aceofbassgreg's comment]

The Rails 3.1 and later ActiveSupport::Concern allows an include module's instance methods to be included directly, so that it's not necessary to create an InstanceMethods module inside the included module. Also it's no longer necessary in Rails 3.1 and later to include M::InstanceMethods and extend M::ClassMethods. So we can have simpler code like this:

require 'active_support/concern'
module M
  extend ActiveSupport::Concern
  # foo will be an instance method when M is "include"'d in another class
  def foo
    "bar"
  end

  module ClassMethods
    # the baz method will be included as a class method on any class that "include"s M
    def baz
      "qux"
    end
  end

end

class Test
  # this is all that is required! It's a beautiful thing!
  include M
end

Test.new.foo # ->"bar"
Test.baz # -> "qux"
Kwh answered 7/1, 2013 at 23:13 Comment(1)
Point of clarification: if, in your model, you extend M::ClassMethods and include M::InstanceMethods, you'll want to add the extend ActiveSupport::Concern logic into the M::InstanceMethods module. Maybe in this case Les is including M in the model (and doesn't have an M::InstanceMethods module?).Circumvent
I
-2

As for Rails 4.x you can use gem scopes_rails

It can generate scopes file and include it to your model.

Also, it can automatically generate scopes for state_machines states.

Irmine answered 2/3, 2016 at 11:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.