Pregunta

Cuando se trabaja con una asociación polimórfica, ¿es posible ejecutar una inclusión en submodelos que solo están presentes en algunos tipos?

Ejemplo:

class Container
  belongs_to :contents, :polymorphic => true
end
class Food
  has_one :container
  belongs_to :expiration
end
class Things
  has_one :container
end

En la vista voy a querer hacer algo como:

<% c = Containers.all %>
<% if c.class == Food %>
  <%= food.expiration %>
<% end %>

Por lo tanto, me gustaría cargar con entusiasmo los vencimientos cuando cargo c, porque sé que necesitaré hasta el último de ellos.¿Hay alguna manera de hacerlo?Simplemente definir un :include regular me genera errores porque no todos los tipos adjuntos tienen una caducidad de submodelo.

¿Fue útil?

Solución

Respuesta editada

Recientemente descubrí que Rails admite la carga ansiosa de asociaciones polimórficas cuando filtras por la columna de tipo polimórfico.Por tanto, no es necesario declarar asociaciones falsas.

class Container
  belongs_to :content, :polymorphic => true
end

Ahora consulta el Container por 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)

Antigua respuesta

Este es un truco ya que no existe una forma directa de incluir objetos polimórficos en una consulta.

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

Ahora consulta el Container por 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)

Eso da como resultado dos llamadas SQL a la base de datos (en realidad son 4 llamadas ya que Rails ejecuta un SQL por cada :include)

No hay forma de hacer esto en un SQL ya que necesita un conjunto de columnas diferente para diferentes tipos de contenido.

Advertencia: Las asociaciones ficticias en Content La clase no debe usarse directamente ya que generará resultados inesperados.

P.ej:Digamos que el primer objeto en el contents La mesa contiene comida.

Content.first.food # will work
Content.first.thing

La segunda llamada no funcionará.Podría darte un Thing objeto con la misma identificación que el Food objeto señalado por Content.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top