有没有办法将命名范围合并到一个新的命名范围?

时间:2008-08-26 20:13:46

标签: ruby-on-rails rails-activerecord named-scope

我有

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

我想要

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

但我宁愿以干燥的方式做这件事。我可以使用

获得相同的效果
 Foo.a(something).b(something_else)

但它并不是特别可爱。

6 个答案:

答案 0 :(得分:8)

至少从3.2开始就有一个聪明的解决方案:

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

答案 1 :(得分:2)

嗯,我还不熟悉rails,我不确定你到底要做什么,但如果你只是为了代码重用,为什么不使用常规类方法呢?


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

你可以通过使用* args代替a和b来使其更灵活,然后可能使一个或另一个可选。如果你坚持使用named_scope,你不能扩展它以做同样的事情吗?

让我知道,如果我完全偏离你想要做的事情。

答案 2 :(得分:1)

通过使其成为类方法,您将无法将其链接到关联代理,例如:

@category.products.ab(x, y)

另一种方法是应用this patch为named_scope启用:through选项:

named_scope :a, :conditions => {}
named_scope :b, :conditions => {}
named_scope :ab, :through => [:a, :b]

答案 3 :(得分:1)

Reusing named_scope to define another named_scope

为方便起见,我将其复制到这里:

您可以使用proxy_options将一个named_scope回收到另一个:

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

这样它就可以与其他named_scopes链接。

我在我的代码中使用它,它完美无缺。

我希望它有所帮助。

答案 4 :(得分:0)

@ PJ:你知道,我已经考虑过了,但是因为我以为我以后无法在第三个​​命名的范围上链接,因为我这样做了:< / p>

Foo.ab(x, y).c(z)

但是,由于ab(x, y)会返回b(y)返回的内容,我认为该链可行。让我重新思考明显的方法!

答案 5 :(得分:0)

退房:

http://github.com/binarylogic/searchlogic

可观!

具体来说:

class Foo < ActiveRecord::Base
  #named_scope :ab, lambda { |a,b| :conditions => { :a => a, :b => b } }
  # alias_scope, returns a Scope defined procedurally
  alias_scope :ab, lambda {
    Foo.a.b
  }
end