2011-10-18 17 views
5

I modelli sono come questo:Come dovrei scrivere ActiveRecord quando ci sono più associazioni?

class Contract < ActiveRecord::Base 
    belongs_to :buyer, :class_name => 'Customer', :foreign_key => 'buyer_customer_id' 
    belongs_to :user, :class_name => 'Customer', :foreign_key => 'user_customer_id' 
    belongs_to :currency 
end 

class Customer < ActiveRecord::Base 
    has_many :as_buyer_in_contracts, :class_name => 'Contract', :foreign_key => 'buyer_customer_id' 
    has_many :as_user_in_contracts, :class_name => 'Contract',:foreign_key => 'user_customer_id' 
end 

class Currency < ActiveRecord::Base 
    has_many :contracts 
end 

E sotto sono i dati:

Contract 
+----+-------------------+------------------+-------------+ 
| id | buyer_customer_id | user_customer_id | currency_id | 
+----+-------------------+------------------+-------------+ 
| 1 |   1   |  3   |  3  | 
| 2 |   2   |  2   |  2  | 
| 3 |   2   |  1   |  2  | 
| |     |     |    | 


Customer 
+----+-------------------+ 
| id |  name  | 
+----+-------------------+ 
| 1 | Terry Brown | 
| 2 | Tom Green  | 
| 3 | Kate White  | 
| |     | 

Currency 
+----+-------------------+ 
| id |  name  | 
+----+-------------------+ 
| 1 |  EUR  | 
| 2 |  USD  | 
| 3 |  JPY  | 
| |     | 

e ora voglio trovare tutti i contratti che hanno stipulato con il cliente il nome di "Terry", in questo modo:

Contract.where("customers.name like '%Terry%'").includes(:buyer,:user) 
#I want 1 and 3, but it can only get 1 
Contract.where("customers.name like '%Terry%'").includes(:user, :buyer) 
#If I write "user" before "buyer", then I can only get 3 

qualcuno mi ha detto che può funzionare in questo modo:

Contract.join(:customer).where("customers.name like '%terry%'").includes(:user,:buyer) 
#It works fine. 

Ho provato e funziona. Ma anche quando il modello Contract appartiene a un altro modello, come currency_id, il metodo sopra non può funzionare di nuovo.

Contract.join(:customer).where("customers.name like '%terry%'").includes(:currency, :user, :buyer) 
#>>Mysql2::Error: Unknown column 'customers_contracts.id' in 'field list': ... 

risposta

0

Hai provato a usare si unisce: acquirente o: utente anziché: cliente?

tuo Modello di contratto non ha: attributo cliente/relazione

Contract.join(:buyer).where("customers.name like '%terry%'").includes(:currency, :user, :buyer) 

mia ipotesi è che sarà equivalente a qualcosa come

Contract.join("INNER JOIN customers ON customers.id = contracts.buyer_customer_id").where("customers.name like '%terry%'").includes(:currency, :user, :buyer) 

controllare il file di log per vedere esattamente ciò che viene generato sql in ogni caso - log/development.log

+0

scusate, ho dimenticato di aggiungere la relazione del modello ... E il file di registro è di circa 40 o 50 linee perché la mia condizione attuale è molto complessa. Ero totalmente confuso da loro. – TerryChen

2

Questo perché non si suppone che utilizzi i join in congiunzione con include. Non è stato sottolineato a sufficienza (e non c'è alcun avviso in rotaie), ma

selezionare, si unisce, gruppo, avendo, ecc non funzionano con include!

È possibile ottenere risultati, ma solo per caso. E le probabilità sono che si rompa prima possibile.

Sembra che ci sia anche qualche incongruenza con include ...

Se è necessario utilizzare un esterno tradizionale unirsi a ActiveRecord> = 3.0 (che è il caso qui) utilizzare l'eccellente squeel gem. Produce davvero il potere di Arel.

provare (con squeel installato):

Contract.joins{buyer.outer}.joins{user.outer}.where("name like '%terry%'") 

L'out of the box join fa interna entrare solo, che esclude tavolo non si intersecano, rendendo il vostro obiettivo impossibile qui: acquirente & utente può escludersi a vicenda. ..

+0

NON FUNZIONA? Li ho usati insieme in altri casi, vuoi dire che potrebbe rompersi in qualsiasi momento? – TerryChen

+0

Questo è un buon candidato per la radice del problema, ma la tua risposta è un po 'vaga all'inizio (seleziona, ecc non funziona con include, inconsistenza). Potresti aggiungere una spiegazione più chiara di questi punti e/o indicare una spiegazione autorevole? –

+0

ancora in vacanza ...cercherò di dare una risposta alla mia risposta un po 'quando torno. – charlysisto

Problemi correlati