2009-09-25 18 views
6

Questa è la mia prima volta con Rails e mi chiedevo se è possibile caricare un ha un'associazione polimorfica in una query SQL? I modelli e le associazioni tra di loro sono essenziali abbastanza: Un modello di asset/tavolo può fare riferimento a un contenuto (un immagine, testo o audio) attraverso un'associazione polimorfica, cioèeager loading delle associazioni polimorfiche in ActiveRecord

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

e l'immagine, testo, audio sono definiti in questo modo:

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

Quando provo a caricare un'immagine, diciamo così:

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

Si specifica due query, uno per recuperare l'immagine e un altro per recuperare la a sset (FYI, questo accade anche se specifichi uno :joins). Sulla base della mia comprensione, ActiveRecord lo fa perché non sa che esiste un'associazione one-to-one tra Image e Asset. C'è un modo per forzare un join e recuperare i 2 oggetti in un colpo solo? Ho anche provato a utilizzare join con una selezione personalizzata, ma alla fine devo creare manualmente i modelli ActiveRecord e le loro associazioni.

Vuol ActiveRecord fornisce un modo per fare questo?

risposta

1

Dopo aver scavato attraverso la sorgente Rails ho scoperto che è possibile forzare un join facendo riferimento un tavolo diverso dal modello attuale in entrambi i selezionati, condizioni o clausole di ordine.

Quindi, se a specificare un ordine sul tavolo Asset:

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

Lo SQL risultante utilizzare un join esterno sinistro e tutto in una dichiarazione. Avrei preferito un join interiore, ma immagino che lo farà per ora.

1

ho corse contro questo problema io stesso. ActiveRecord punta più verso la fine di rendere più facile per Rubyists (che potrebbe non essere nemmeno troppo familiare con SQL) per interfacciarsi con il database, che con le chiamate di database ottimizzate. Potrebbe essere necessario interagire con il database a un livello inferiore (ad es. DBI) per migliorare le prestazioni. L'utilizzo di ActiveRecord influirà sicuramente sulla progettazione dello schema.

Il desiderio di efficienza SQL mi ha fatto pensare di usare altri ORM. Non ne ho trovato uno adatto alle mie esigenze. Anche quelli che si muovono di più verso lo stesso SQL di Transact (ad esempio Sequel) hanno una pesante API di Ruby. Sarei soddisfatto senza un'API di tipo Ruby e semplicemente scrivendo manualmente il mio T-SQL. Il vero vantaggio che sto cercando con un ORM è la M, che mappa il set di risultati (di una o più tabelle) negli oggetti.

+0

Normalmente non uso più gli ORM. Questa è un'astrazione che ho fatto senza. – Mario

1

(questo è per Rails 3 sintassi.)

MetaWhere è un gioiello impressionante per fare query complesse che si trovano al di fuori del consueto dominio di ActiveRecord facile e ruby-like. (@wayne:. Supporta outer join così)

https://github.com/ernie/meta_where

polimorfico si unisce sono un po 'più complicato.Ecco come ho fatto la mia con MetaWhere:

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

In realtà, ho fatto un metodo comodo nel mio-associazione-avere polimorfica classe:

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

Così sarà sempre interrogare & carico desiderosi di un particolare tipo del bene. Non ho provato a mescolarlo con più tipi di join in una query. Poiché il polimorfismo funziona utilizzando la stessa chiave esterna per fare riferimento a tabelle diverse, a livello SQL è necessario specificarlo come join separati perché unire solo join a una tabella.

Questo funziona solo con ActiveRecord 3 perché si ha accesso alla straordinaria potenza di AREL.

Problemi correlati