2010-04-22 6 views
5

Hai problemi con AR 2.3.5, ad esempio:Come forzare il tipo di attributo ActiveRecord restituito da: selezionare la frase sulla tabella unita?

users = User.all(:select => "u.id, c.user_id", :from => "users u, connections c", 
     :conditions => ...) 

Returns, ad esempio:

=> [#<User id: 1000>] 
>> users.first.attributes 
=> {"id"=>1000, "user_id"=>"1000"} 

Nota che AR restituisce il id del modello cercato come numerico, ma il selezionato user_id del modello unito come String, sebbene entrambi siano int(11) nello schema del database.

Come è possibile formulare meglio questo tipo di query per selezionare colonne di tabelle che supportano più modelli e recuperano il loro tipo naturale anziché String? Sembra che l'AR stia puntando su questo da qualche parte. Come potrei forzare i tipi restituiti al tempo di caricamento AR e non dover virare .to_i (ecc.) Su ogni accesso post-hoc?

+1

Ci può spiegare cosa significa "connessioni" è, e come è collegato agli utenti? – kikito

risposta

1

Perché stai usando: da => "utenti" all'interno di un User.method? Di seguito vi do un inner join (che è quello che sta facendo in ogni modo)

users = User.all(:include => :connections, :select => "users.id, connections.user_id", :conditions => {...}) 

Questo sta per essere richiesta molto pesante per il database. Tuttavia, la query più veloce sarebbe con il join esterno.

Questo sarà anche restituire le chiavi come INT non STRING

Un'alternativa molto più veloce era

Connection.all(:include => :user, :conditions => {...}).collect {|e| [e.user_id, e.id] } 

Questo vi dà un array di array con gli ID. Se si selezionano solo le colonne "id, user_id", allora potrebbe non essere necessariamente come oggetto AR. Un array può essere più veloce.

Spero di non mancare un punto qui. Suggeriscimi, se lo sono.

+0

Il da: è stato incluso per l'alias dei nomi delle colonne della tabella. Ci sono condizioni secondarie che vengono mescolate dinamicamente. Prenderò in considerazione il tuo approccio e farò dei test con esso - grazie. – tribalvibes

2

Purtroppo non succederà molto facilmente. Tutti i dati dalla connessione DB arrivano ai binari come stringhe, la conversione dei tipi avviene in ciascuno dei metodi di attributo dinamico che le rotaie creano in fase di runtime. Conosce quali attributi convertire in quale tipo dai metadati di tipo colonna di tipo tabella che recupera all'avvio dell'app. Ogni modello ha solo metadati di colonna per le proprie colonne, ecco perché le proprie colonne finiscono con il tipo corretto. Non esiste un modo semplice per convertire automaticamente i tipi corretti.

Si potrebbe invece creare un semplice metodo di conversione che prenderebbe un hash e convertirà automaticamente gli attributi.

Qualcosa di simile a questo:

users = User.all(:select => "cl, comments.c2", ...) 
users = convert_columns(users, 'c2' => :integer, 'other_column' => :date) 

def convert_columns(records, columns = {}) 
    records.each do |rec| 
    columns.each do |col, type| 
     rec[col] = case type 
     when :int then rec[col].to_i 
     when :date then ........ 
     .... 
     end 
    end 
    end 
end 
0

Se si desidera una soluzione rapida - cercare di utilizzare after_find callback e preimpostato corretta attributi tipi ci:

class User < ActiveRecord::Base 

    after_find :preset_types 


    private 
    def preset_types user 
    user.user_id = user.user_id.to_i 
    end 

end