2009-09-25 23 views
6

Esta es la primera vez que uso Rails y me preguntaba si es posible cargar una asociación polimórfica tiene una en una consulta SQL. Los modelos y las asociaciones entre ellos son lo suficientemente básicas: Un modelo de activo/table puede referirse a un contenido (ya sea una imagen, texto o audio) a través de una asociación polimórfica, es decir,Carga ansiosa de asociaciones polimórficas en ActiveRecord

 
class Asset < ActiveRecord::Base 
    :belongs_to :content, :polymorphic => true 
end 

y la Imagen, texto, audio se definen así:

 
class Image < ActiveRecord::Base 
    :has_one :asset, :as => :content 
end 

Cuando intento cargar una imagen, digamos así:

Image.first(
     :conditions => {:id => id}, 
     :include => :asset 
)

se especifica dos consultas, una para recuperar la imagen y otro para recuperar la a Sys (FYI, esto sucede también si especifico un :joins). Según lo que entiendo, ActiveRecord hace esto porque no sabe que existe una asociación uno a uno entre Image y Asset. ¿Hay alguna manera de forzar una unión y recuperar los 2 objetos de una vez? También intenté usar join con una selección personalizada, pero al final tengo que crear manualmente los modelos de ActiveRecord y sus asociaciones.

¿ActiveRecord proporciona una manera de hacer esto?

Respuesta

1

Después de explorar la fuente de Rails, he descubierto que puede forzar una unión haciendo referencia a una tabla que no sea el modelo actual, ya sea en las cláusulas de selección, condiciones o pedido.

lo tanto, si puedo especificar una orden en la tabla de activos:

 
Image.first(
     :conditions => {:id => id}, 
     :include => :asset, 
     :order => "asset.id" 
) 

El SQL resultante utilizará una combinación externa izquierda y todo en un comunicado. Hubiera preferido una unión interna, pero supongo que esto servirá por ahora.

1

Me encontré con este problema yo mismo. ActiveRecord se inclina más hacia el fin de facilitar que los Rubyistas (que ni siquiera están demasiado familiarizados con SQL) interactúen con la base de datos, de lo que lo hace con las llamadas optimizadas a la base de datos. Es posible que deba interactuar con la base de datos en un nivel inferior (por ejemplo, DBI) para mejorar su rendimiento. El uso de ActiveRecord definitivamente afectará la forma en que diseñe su esquema.

El deseo de la eficiencia de SQL me hizo pensar sobre el uso de otros ORM. No he encontrado uno para satisfacer mis necesidades. Incluso aquellos que se mueven más hacia transacciones SQL en sí (por ejemplo, Sequel) tienen una pesada API de Ruby. Me contentaría sin una API similar a Ruby y solo escribiría manualmente mi T-SQL. El beneficio real que persigo con un ORM es el M, mapeando el conjunto de resultados (de una o más tablas) en los objetos.

+0

Normalmente, ya no uso ORMs. Esta es una abstracción que he hecho bien sin ella. – Mario

1

(Esto es para Rails 3 sintaxis.)

MetaWhere es una joya impresionante para hacer consultas complejas que están fuera del ámbito habitual de ActiveRecord fácil y rubí similares. (@wayne:. Es compatible con combinaciones externas así)

https://github.com/ernie/meta_where

polimórfica une son un poco más difícil.Así es como yo hice la mía con MetaWhere:

Image.joins(:asset.type(AssetModel)).includes(:asset) 

De hecho, hice un método de conveniencia en mi polimórfico asociación que tiene clase:

def self.join_to(type) 
    joins(:asset.type(type)).includes(:asset) 
    end 

lo tanto, siempre se consulta & carga ansiosa un tipo particular de activo. No he intentado mezclarlo con varios tipos de unión en una consulta. Debido a que el polimorfismo funciona utilizando la misma clave externa para hacer referencia a tablas diferentes, en el nivel de SQL debe especificarlo como uniones separadas porque una combinación solo se une a una tabla.

Esto solo funciona con ActiveRecord 3 porque tiene acceso a la increíble potencia de AREL.

Cuestiones relacionadas