rails嵌套has_many与外部作用域连接未命中连接表:sql错误

时间:2014-02-18 21:29:43

标签: sql ruby-on-rails ruby-on-rails-4 rails-activerecord has-many-through

github gist中提供了一个自运行模板,其中包含所有要自行测试的模型 - 运行它并触发错误。

为了使其可视化,结构如下所示:

Colors
  |n|
  |:|
  |1| -----
Houses n:n Conditions
  |n| -----
  |:|
  |1|
People

从空白数据库开始,我创建了一些测试数据(控制台命令,省略了返回值以保持清晰):

irb(main):001:0> Condition.create(condition: :damaged)
irb(main):002:0> house = House.create(conditions: [Condition.first])
irb(main):003:0> person = Person.create
irb(main):004:0> house.person = person
irb(main):005:0> house.save

所以现在我有一些测试数据。让我们检索一下这个人的房子(根据定义,这只是受损房屋):

irb(main):006:0> person.damaged_houses
  House Load (0.2ms)
  SELECT "houses".* FROM "houses" 
    INNER JOIN "conditions_houses" ON "conditions_houses"."house_id" = "houses"."id"
    INNER JOIN "conditions" ON "conditions"."id" = "conditions_houses"."condition_id"
    WHERE "houses"."person_id" = ? AND "conditions"."condition" = 'damaged'
    [["person_id", 1]]
=> #<ActiveRecord::Associations::CollectionProxy [#<House id: 1, person_id: 1>]>

一切顺利,返回损坏的房子并且sql正确地加入了conditions表。现在我想得到人的所有颜色,这被定义为房屋的所有颜色,房屋仍然只是受损的房屋。这应该返回一个空集合(因为数据库中还没有颜色)。

irb(main):007:0> person.damaged_colors
  Color Load (0.4ms) 
  SELECT "colors".* FROM "colors"
    INNER JOIN "houses" ON "colors"."house_id" = "houses"."id" 
    WHERE "houses"."person_id" = ? AND "conditions"."condition" = 'damaged'
    [["person_id", 1]]
SQLite3::SQLException: no such column: conditions.condition:
  SELECT "colors".* FROM "colors"
    INNER JOIN "houses" ON "colors"."house_id" = "houses"."id"
    WHERE "houses"."person_id" = ? AND "conditions"."condition" = 'damaged'

从sql字符串中可以清楚地看到连接表conditions缺失,因此conditions.condition不可用。如果我看到它正确,只需要查询之前的字符串:

INNER JOIN "conditions_houses" ON "conditions_houses"."house_id" = "houses"."id"
INNER JOIN "conditions" ON "conditions"."id" = "conditions_houses"."condition_id"

所以查询应该是:

SELECT "colors".* FROM "colors"
  INNER JOIN "houses" ON "colors"."house_id" = "houses"."id"
  INNER JOIN "conditions_houses" ON "conditions_houses"."house_id" = "houses"."id"
  INNER JOIN "conditions" ON "conditions"."id" = "conditions_houses"."condition_id"
  WHERE "houses"."person_id" = ? AND "conditions"."condition" = 'damaged'

这是一个rails bug还是我做错了?为什么缺少联接conditions

代码:

class Color < ActiveRecord::Base
    belongs_to :house
end

class Condition < ActiveRecord::Base
    has_and_belongs_to_many :houses
end

class House < ActiveRecord::Base
    has_many :colors
    belongs_to :person

    has_and_belongs_to_many :conditions

    scope :damaged, -> { joins(:conditions).where(:'conditions.condition' => 'damaged') }
end

class Person < ActiveRecord::Base
    has_many :damaged_houses, -> { damaged }, :class_name => "House"
    has_many :damaged_colors, through: :damaged_houses, :source => :colors
end

1 个答案:

答案 0 :(得分:1)

所以我能够通过修改以下内容来让你的要点得以运行:

has_many :damaged_colors, through: :damaged_houses, :source => :colors

has_many :damaged_colors, -> { joins({house: :conditions}).where(:'conditions.condition' => 'damaged') }, through: :damaged_houses, :source => :colors

在评论中提到的HABTM关联似乎是一个ActiveRecord错误...希望这有助于平均时间......

有趣的是,我把你的要点改为hm:hm并且有同样的问题......