我使用STI模式实现了一个类层次结构
class A
scope :aaa, where([someField]:[someValue])
end
class B < A
end
问题在于,当我尝试打电话时:
B.limit(5).aaa
=> SELECT "[table]".* FROM "[table]" WHERE "[table]"."type" IN ('A') AND ([someField] = [someValue]) LIMIT 5
所以我得到了5个类型A的对象,它们满足范围:aaa 但是我需要对type =“B”
的行做同样的事情有没有办法使用父级的范围,而不是在STI模式的子级中重新划分它?
提前致谢
EDITED
我刚刚和我的朋友讨论过,他向我展示了一件重要的事情。 A不是STI的根类。实际上整个层次结构看起来像
class O < ActiveRecord::Base
end
class A < O
scope ..... .....
end
class B < A
end
也许原因在于层次结构本身?...
答案 0 :(得分:2)
这是正确的,这是多级层次结构的结果。
如果您只有一个级别的继承(即A
继承自ActiveRecord::Base
而不是继承自O
),则范围将按预期工作。
一旦有中间类,Rails中的STI并不总是按预期工作。
我不确定这是否是Rails中的错误,或者仅仅因为它无法准确推断出应该做什么。我将不得不研究更多。
您遇到的范围问题只是意外行为的一个示例。另一个例子是查询中间类只会查询它所知道的类类型,除非你特别要求它们,否则它们可能不包括它的所有子类:
有关更多信息,请参阅以下主题,特别是MatthewRudy底部的帖子:https://groups.google.com/forum/#!topic/hkror/iCg3kxXkxnA
如果您仍想使用范围而不是@Atastor建议的类方法,则可以将范围放在O
而不是A
上。这并不理想,因为范围可能不适用于O
的每个子类,但它确实会导致Rails查询type
列中的正确类,并且是一种快速的解决方法。 / p>
答案 1 :(得分:1)
我会切换到使用类方法而不是范围,例如在A级
def self.aaa
A.where([someField]:[someValue])
end
之后在B级
def self.bbb
self.aaa.where("type = ?","B")
end
答案 2 :(得分:0)
注意STI中级课程,因为它会影响你正在尝试的范围。
在我的情况下,我有:
class A < ActiveRecord
blabla
end
class B < A
scope :dates, ->(start_date, end_date) { where(:date => start_date..end_date) }
end
class C < B
<call scope_dates>
end
class D < B
<call scope_dates>
end
范围实际上包括C级和D级组合。
所以,如果你在Rails中有STI请将范围放在Base类中,而不是中间类