如何通过抽象活动记录向子类添加范围

时间:2011-03-23 20:50:57

标签: 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 var
end

class Subclass2 << MySuperClass
# has attribute var
end

所以现在我想打电话

Subclass1.scopeForAllSubclasses123).all

Subclass2.scopeForAllSubclasses(123).all

总的来说,我想要一组所有已经通过设计实现此范围的类,而不仅仅是因为开发人员决定这样做。

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

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

这会将范围注入每个实例。

答案 1 :(得分: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解决方案更清洁,更容易。