2015-05-05 8 views
10

Fonti:Rails 3 aggiungendo il nome del database di tabella non sia include di default a carico desiderosi

Il mio progetto si sta muovendo verso avere più database (attualmente sullo stesso server) e vorrei poter unire tra questi database. Per fare questo, ho bisogno di aggiungere il nome del database per il prefisso delle tabelle in questo modo:

class FirstBase < ActiveRecord::Base 
    def self.table_name_prefix 
     "DBNAME.t_" 
    end 

    establish_connection :firstdb 
end 

class User < FirstBase 
    has_many :user_roles 
end 

class UserRole < FirstBase 
    belongs_to :user 
end 

aggiungendo il prefisso nome della tabella sembra influenzare il comportamento predefinito include sulla stessa query, anche all'interno dello stesso database . Considerare User.includes(:user_roles).first

Senza nome della tabella prefisso:

User Load (67.1ms) SELECT * FROM t_userst_users LIMIT 1 UserRole carico (84.5ms) SELECT * FROM t_user_rolest_user_roles DOVE t_user_roles... user_id IN (1)

Con il nome della tabella prefisso:

SQL (76.8ms) SELECT DISTINCT DBNAME. t_users .id DA DBNAME. t_users LEFT OUTER JOIN DBNAME. t_user_roles SU DBNAME. t_user_roles. user_id = DBNAME. t_users. id LIMIT 1

SQL (66,4 ms) SELEZIONARE DBNAME. t_users. id AS t0_r0, DBNAME. t_users. email AS t0_r1, DBNAME. t_user_roles. id AS t1_r0, DBNAME. t_user_roles. user_id AS t1_r1 DAL DBNAME. t_users LEFT OUTER JOIN DBNAME. t_user_roles SU DBNAME. t_user_roles. user_id = DBNAME. t_users. id DOVE DBNAME. t_users. id IN (1)

In altre parole, il comportamento predefinito delle chiamate include è cambiato da pre-caricamento a carico bisognoso.

Qualcuno sa perché il comportamento predefinito sta cambiando? Ci deve essere qualcosa nell'aggiungere il nome del database che fa pensare a Rails che dobbiamo caricarci con rabbia, ma non vedo perché. Sono anche sorpreso di vedere questo come immagino non sia insolito aggiungere il nome del database. Posso forzare bruto-forzare questo nella nostra base di codice cambiando tutto include al precaricamento, ma mi piacerebbe capire cosa sta succedendo qui. C'è un modo per cambiare il comportamento predefinito?

+0

'FirstBase' è una classe astratta? ('self.abstract_class = true'). La mia ipotesi è che la logica STI possa interferire con la generazione SQL qui. Forse provi ad estrarre questa logica in un modulo/preoccupazione? (Si noti inoltre che i modelli con namespace usano il parametro table_name_prefix del loro modulo genitore). D'altra parte, AFAIK l'effettivo SQL generato da 'includes' è" comportamento indefinito "e dipende dall'adattatore DB. –

risposta

1

Il problema è che il table_name_prefix introduce un punto. Questo confonde la logica che cerca di determinare se dovrebbe precaricare o caricare carico. Questo è un bug di Rails 3 ed è stato risolto in Rails 4.Se hai bisogno di un comportamento specifico in Rails 3, devi specificare esplicitamente preload o eager_load come indicato nella tua domanda.

In ActiveRecord::Relation, exec_queries chiamate eager_loading? per decidere se dovrebbe caricare carico. Ciò richiede references_eager_loaded_tables? che utilizza tables_in_string per cercare di trovare i nomi delle tabelle nella query SQL che non fanno parte delle tabelle unite:

# ActiveRecord::Relation#references_eager_loaded_tables? 
(tables_in_string(to_sql) - joined_tables).any? 

Il metodo tables_in_string sarebbe valido poiché non sempre analizza correttamente lo SQL . Questo codice può essere utilizzato per rivedere quello che pensa sono i nomi di tabella nella query SQL:

relation = User.includes(:user_roles) 
relation.send(:tables_in_string, relation.to_sql) 

Con il prefisso del nome DBNAME.t_ tavolo, questo darà ["DBNAME", "t_users"] come i nomi di tabella, che è sbagliato. Dovrebbe dare ["DBNAME.t_users"].

Un problema simile è stato documentato in ActiveRecord query changing when a dot/period is in condition value. Ciò ha portato a modifiche in ActiveRecord::Relation che si è spostato dall'uso di tables_in_string quando si decide se caricare o caricare prima.

+0

Grazie per la risposta dettagliata! Esattamente quello che stavo cercando. – raja