Рассмотрим следующие модели:
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)
Это приводит к дублированию тегов из-за того, что: секунды неправильно соединяются с таблицей тегов, как в первом случае выше (см. Третью строку выражения 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
парню, который подтвердил, что это ошибка, «если вы определите ассоциацию в базовом классе, она будет работать, как ожидалось».Кто-нибудь знает, что это значит / как это сделать?