gpt4 book ai didi

ruby-on-rails - ActiveRecord 为 has_many 生成的错误 sql :through relation with STI

转载 作者:太空宇宙 更新时间:2023-11-03 16:37:39 24 4
gpt4 key购买 nike

考虑这些模型:

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' 关系,但是其中一个模型(第三个)是从另一个(第二个)继承的 STI。

假设我想做一个连接以查看 Third 的所有实例以获得 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)

这会导致标签重复,因为 :seconds 没有像上面第一种情况那样与标签表正确连接(请参阅每种情况下的 sql 语句的第三行)。所有带标签的首字母都将显示在结果表中,WHERE 子句完全无效。

如果还有其他需要说明的,我还没有遇到过。如果有人知道如何强制执行此操作,请告诉我。否则,我假设这是 Rails 中的错误。哦,请不要建议我使用将被弃用的旧 model.find() 方法。

更新:

https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/6608-generated-sql-for-has_many-through-relation-wrong-when-used-with-sti

因此,据确认这是一个错误的人说,“如果您在基类中定义关联,它会按预期工作。”有谁知道这意味着什么/如何做到这一点?

最佳答案

查询中的小变化:

@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

关于ruby-on-rails - ActiveRecord 为 has_many 生成的错误 sql :through relation with STI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5406456/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com