Is there a way to combine named scopes into a new named scope?

11,273

Solution 1

Well I'm still new to rails and I'm not sure exactly what you're going for here, but if you're just going for code reuse why not use a regular class method?


        def self.ab(a, b)
            a(a).b(b)
        end
    

You could make that more flexible by taking *args instead of a and b, and then possibly make one or the other optional. If you're stuck on named_scope, can't you extend it to do much the same thing?

Let me know if I'm totally off base with what you're wanting to do.

Solution 2

At least since 3.2 there is a clever solution :

scope :optional, ->() {where(option: true)}
scope :accepted, ->() {where(accepted: true)}
scope :optional_and_accepted, ->() { self.optional.merge(self.accepted) }

Solution 3

Yes Reusing named_scope to define another named_scope

I copy it here for your convenience:

You can use proxy_options to recycle one named_scope into another:

class Thing
  #...
  named_scope :billable_by, lambda{|user| {:conditions => {:billable_id => user.id } } }
  named_scope :billable_by_tom, lambda{ self.billable_by(User.find_by_name('Tom').id).proxy_options }
  #...
end

This way it can be chained with other named_scopes.

I use this in my code and it works perfectly.

I hope it helps.

Share:
11,273
James A. Rosen
Author by

James A. Rosen

Updated on June 27, 2022

Comments

  • James A. Rosen
    James A. Rosen almost 2 years

    I have

    class Foo < ActiveRecord::Base
      named_scope :a, lambda { |a| :conditions => { :a => a } }
      named_scope :b, lambda { |b| :conditions => { :b => b } }
    end
    

    I'd like

    class Foo < ActiveRecord::Base
      named_scope :ab, lambda { |a,b| :conditions => { :a => a, :b => b } }
    end
    

    but I'd prefer to do it in a DRY fashion. I can get the same effect by using

     Foo.a(something).b(something_else)
    

    but it's not particularly lovely.

  • aceofspades
    aceofspades over 13 years
    Caveat is that proxy_options only returns the scope of the latest named scope, so this cannot be done against another derived named scope
  • KARASZI István
    KARASZI István about 13 years
    With this solution it won't behave the scope as a normal scope does. For e.g. it won't be in Model.scopes.