Ruby on rails 如何通过抽象活动记录向子类类添加作用域

Ruby on rails 如何通过抽象活动记录向子类类添加作用域,ruby-on-rails,inheritance,scope,Ruby On Rails,Inheritance,Scope,我希望有几个子类都应该有一个作用域(同名)。虽然我知道直接继承是不可能的,但基本思想如下: class MySuperClass << ActiveRecord::Base abstract_class = true scope :scopeForAllSubclasses , lambda {|my_var| where(:var => my_var )} end class Subclass1 << MySuperClass #has attribute va

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

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

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


有什么想法吗?

您可以使用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

这将把作用域注入每个实例。

我今天遇到了同样的问题,并找到了上述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
class MySuperClass my\u var)
结束
结束
ScopeForAllSubclass('something')#=>返回所有子类的结果
Subclass 1.ScopeForAllSubclass('something')#=>只返回子类1的结果
ScopeForAllSubclass('something')#=>只返回子类2的结果

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

这是一个很好的解决方案。然而:在超类上定义的子类和作用域在Rails2.X中工作,所以Rails3在这方面是一个倒退…:(这有一个限制,即一旦检索到记录数组,您就无法应用范围来修剪它们,但对于基本查询,效果很好!很抱歉,我不理解您所说的“一旦检索到记录数组,就修剪它们”是什么意思。”。您也不能将作用域应用于已获取对象的数组…而我的回答return/中解释的方法作用域只是作用域,因此您可以像作用域一样链接它们。。。
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
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