考虑这些模型:
class First < ActiveRecord::Base
has_many :tags
has_many :thirds, :through => :tags
end
class Second < ActiveRecord::Base
end
class Third < Second
has_many :tags
has_many :firsts, :through => :tags
end
class Tag < ActiveRecord::Base
belongs_to :first
belongs_to :third
end
换句话说,我们有一个has_many:through'tag-style'关系,但其中一个模型(Third)是继承自另一个(第二个)的STI。
假设我想进行连接,以查看First的所有实例,以获得First的某些值:
@thirds = Third.joins(:firsts).where("first.id = 2")
这将按预期工作;生成的sql(通过to_sql)为:
SELECT `seconds`.* FROM `seconds`
INNER JOIN `tags` ON `seconds`.`id` = `tags`.`third_id`
INNER JOIN `firsts` ON `firsts`.`id` = `tags`.`first_id`
WHERE `seconds`.`type` = 'Third' AND (first.id = 1)
这不适用于另一个方向:
@firsts = First.joins(:thirds).where("second.id = 2")
生成的SQL是:
SELECT `firsts`.* FROM `firsts`
INNER JOIN `tags` ON `firsts`.`id` = `tags`.`first_id`
INNER JOIN `seconds` ON `seconds`.`type` = 'Third'
WHERE (second.id = 2)
这会导致标记重复,因为以下事实:秒与标记表没有正确连接,如上面的第一种情况(参见每种情况下sql语句的第三行)。带有标签的所有第一个将显示在结果表中,WHERE子句完全无效。
如果需要指定别的东西,我还没有碰到它。如果有人知道如何强迫这项工作,请告诉我。否则,我假设这是Rails中的一个错误。哦,请不要建议我使用旧的model.find()方法,这些方法将被弃用。
更新:
因此,根据确认这是一个错误的人,'如果你在基类中定义关联,它按预期工作。' 有谁知道这意味着什么/如何做到这一点?
答案 0 :(得分:1)
您的查询几乎没有变化:
@thirds = Third.joins(:firsts).where(:firsts => {:id => 2})
@firsts = First.joins(:thirds).where(:thirds => {:id => 2})
我认为你应该尝试在你的STI模型中添加一些coomon的东西:
class Third < Second
has_many :tags
has_many :firsts, :through => :tags
def self.model_name
name = "seconds"
name.instance_eval do
def plural; pluralize; end
def singular; singularize; end
def i18n_key; singularize; end
def human(*args); singularize; end
end
return name
end
end
并查看这篇精彩的阅读http://code.alexreisner.com/articles/single-table-inheritance-in-rails.html
或者您可以在该链接中阅读,您可以使用这种看起来不太清晰的方法
def self.inherited(child)
child.instance_eval do
def model_name
Second.model_name
end
end
super
end