Ruby on Rails :: включают в полиморфную ассоциацию с подмодельками
Вопрос
При работе с полиморфной ассоциацией можно ли запустить включение на подмодельки, которые присутствуют только в некоторых типах?
Пример:
class Container
belongs_to :contents, :polymorphic => true
end
class Food
has_one :container
belongs_to :expiration
end
class Things
has_one :container
end
В поле зрения я хочу сделать что-то вроде:
<% c = Containers.all %>
<% if c.class == Food %>
<%= food.expiration %>
<% end %>
Поэтому я хотел бы стремиться загрузить скорость, когда я загружаю C, потому что я знаю, что мне понадобится каждый последний из них. Есть ли способ сделать это? Просто определяя регулярное: включить, получает мне ошибки, потому что не все прилагаемые типы имеют срок действия подмодера.
Решение
Отредактированный ответ
Недавно я узнал, что Rails поддерживает нетерпеливую загрузку полиморфных ассоциаций при фильтре по столбцу полиморфного типа. Так что нет необходимости объявлять поддельных ассоциаций.
class Container
belongs_to :content, :polymorphic => true
end
Теперь запрос Container
к container_type
.
containers_with_food = Container.find_all_by_content_type("Food",
:include => :content)
containers_with_thing = Container.find_all_by_content_type("Thing",
:include => :content)
Старый ответ
Это взлом, поскольку нет прямого способа включить полиморфные объекты в одном запросе.
class Container
belongs_to :contents, :polymorphic => true
# add dummy associations for all the contents.
# this association should not be used directly
belongs_to :food
belongs_to :thing
end
Теперь запрос Container
к container_type
.
containers_with_food = Container.find_all_by_content_type("Food",
:include => :food)
containers_with_thing = Container.find_all_by_content_type("Thing",
:include => :thing)
Это приводит к двум вызовам SQL в базу данных (на самом деле это 4 звонка, поскольку Rails выполняет один SQL для каждого :include
)
Нет никакого способа сделать это в одном SQL, так как вам нужен другой столбец для разных типов контента.
Предостережение: Манекенные ассоциации на Content
Класс не должен использоваться напрямую, так как оно приведет к неожиданным результатам.
Например: позволяет сказать первый объект в contents
Стол содержит еду.
Content.first.food # will work
Content.first.thing
Второй звонок не будет работать. Это может дать вам Thing
объект с тем же идентификатором, что и Food
Объект указал Content
.