【问题标题】:how can I add a scope to subclass class through abstract active record如何通过抽象活动记录向子类添加范围
【发布时间】:2011-07-21 15:40:13
【问题描述】:

我希望有几个子类都应该有一个范围(同名)。虽然我知道直接继承是不可能的,但基本思想如下:

class MySuperClass << ActiveRecord::Base
abstract_class = true
scope :scopeForAllSubclasses , lambda {|my_var| where(:var => my_var )}
end

class Subclass1 << MySuperClass
#has attribute var
end

class Subclass2 << MySuperClass
# has attribute var
end

所以现在我想打电话

Subclass1.scopeForAllSubclasses123).all

Subclass2.scopeForAllSubclasses(123).all

我想要一组类都通过设计实现了这个范围,而不是仅仅因为开发人员决定这样做。

有什么想法吗?

【问题讨论】:

    标签: ruby-on-rails inheritance scope


    【解决方案1】:

    您可以使用 mixin 而不是超类来做到这一点:

    module ScopeBuddy
      def self.included base
        base.instance_eval "scope :scopeForAllSubclasses , lambda {|my_var| where(:var => my_var )}"
      end
    end
    
    class ClassA
      include ScopeBuddy
    end
    
    class ClassB
      include ScopeBuddy
    end
    

    这会将作用域注入到每个实例中。

    【讨论】:

    • 这是一个不错的解决方案。然而:在超类上定义的子类和作用域在 Rails 2.X 中工作,所以 Rails 3 在这方面倒退了一步...... :(
    【解决方案2】:

    我今天遇到了同样的问题,并找到了上面提供的 mixin 解决方案的替代方案。感谢 Arel,.where.order 等都返回作用域。所以你实际上可以用类方法替换你的范围:

    class MySuperClass << ActiveRecord::Base
      abstract_class = true
    
      def self.scopeForAllSubclasses(my_var)
        where(:var => my_var)
      end
    end
    
    MySuperClass.scopeForAllSubclasses('something') # => returns results from all subclasses
    Subclass1.scopeForAllSubclasses('something')    # => returns results from just Subclass1
    Subclass2.scopeForAllSubclasses('something')    # => returns results from just Subclass2
    

    我发现这种方法在几乎所有情况下都比 mixin 解决方案更清洁、更容易。

    【讨论】:

    • 这有一个限制,即一旦检索到记录数组,您就无法应用范围来修剪记录数组,但对于基本查询,效果很好!
    • 很抱歉,但我不明白您所说的“一旦检索到记录数组就删除它们”是什么意思。您也不能将作用域应用于获取的对象数组...并且我的答案中解释的 method-scopes 只是作用域,因此您可以像作用域一样链接它们...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多