【问题标题】:Is there a way to combine named scopes into a new named scope?有没有办法将命名范围组合成一个新的命名范围?
【发布时间】:2008-08-26 20:13:46
【问题描述】:

我有

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

但我更喜欢以 DRY 的方式进行。我可以通过使用获得相同的效果

 Foo.a(something).b(something_else)

但它并不是特别可爱。

【问题讨论】:

  • 似乎这种行为在rails中不是默认的。

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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    好吧,我对 Rails 还是很陌生,我不确定您在这里到底要做什么,但是如果您只是为了代码重用,为什么不使用常规的类方法呢?

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

    您可以通过使用 *args 而不是 a 和 b 来使其更加灵活,然后可能使其中一个或另一个可选。如果你被困在 named_scope 上,你不能扩展它来做同样的事情吗?

    如果我对你想做的事情完全不满意,请告诉我。

    【讨论】:

    • 有了这个解决方案,它的作用域就不会像普通作用域那样。例如它不会在Model.scopes
    【解决方案3】:

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

    @category.products.ab(x, y)
    

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

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

    【讨论】:

      【解决方案4】:

      是的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链接。

      我在我的代码中使用了它,它运行良好。

      希望对你有帮助。

      【讨论】:

      • 需要注意的是 proxy_options 只返回最新命名范围的范围,因此不能针对另一个派生的命名范围进行此操作
      【解决方案5】:

      @PJ:你知道,我曾考虑过这一点,但因为我认为我以后无法在 第三个​​ 命名范围上进行链接,所以我放弃了它,就像这样:

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

      但是由于ab(x, y) 返回b(y) 将返回的任何内容,我认为链会起作用。让我重新思考显而易见的事情的方法!

      【讨论】:

        【解决方案6】:

        退房:

        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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-09-23
          • 2022-11-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多