2010-04-22 12 views
5

Tiene problemas con AR 2.3.5, por ejemplo:Cómo forzar el tipo de atributo ActiveRecord devuelto por: ¿seleccionar frase en la tabla unida?

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

devoluciones, por ejemplo:

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

Tenga en cuenta que AR devuelve el id del modelo buscados como numérico, pero el seleccionado user_id del modelo unido como String, aunque ambos son int(11) en el esquema de la base de datos.

¿Cómo podría formar mejor este tipo de consulta para seleccionar columnas de tablas que respaldan varios modelos y recuperar su tipo natural en lugar de String? Parece que AR está pateando esto en alguna parte. ¿Cómo podría forzar los tipos devueltos en el tiempo de carga de AR y no tener que marcar .to_i (etc.) en cada acceso post hoc?

+1

Puede explicar lo que "conexiones" que es, y cómo se relaciona a los usuarios? – kikito

Respuesta

1

¿Por qué utiliza: a => "usuarios" dentro de un User.method? El siguiente será hacer una unión interna (que es lo que está haciendo de todos modos)

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

Esto va a ser muy pesada para la consulta de la base de datos. Sin embargo, la consulta más rápida sería con la combinación externa.

Esto también devolver las llaves como INT no CADENA

Una alternativa mucho más rápida fue

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

Esto le da una matriz de matrices con los identificadores. Si va a seleccionar únicamente columnas "id, user_id", puede que no sea necesariamente como objeto AR. Una matriz puede ser más rápida.

Espero que no me falte algo de sentido aquí. Sugerirme, si lo soy.

+0

El desde: se incluyó a alias los nombres de columna de la tabla. Hay subcondiciones que se mezclan de forma dinámica. Consideraré su enfoque y haré algunas pruebas con él, gracias. – tribalvibes

2

Desafortunadamente no va a suceder muy fácilmente. Todos los datos de la conexión DB llegan a los rieles como cadenas, la conversión de tipos ocurre en cada uno de los métodos de atributos dinámicos que los rieles crean en tiempo de ejecución. Sabe qué atributos convertir a qué tipo por los metadatos del tipo columna de la tabla que recupera cuando se inicia la aplicación. Cada modelo solo tiene metadatos de columna para sus propias columnas, por eso sus propias columnas terminan con el tipo correcto. No hay una forma fácil de convertir automáticamente a los tipos correctos.

Podría, por otro lado, crear un método de conversión simple que tomaría un Hash y automáticamente convertiría los atributos.

Algo como esto:

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

Si quieren una solución rápida - trate de usar after_find devolución de llamada y preestablecido correcta atributos de tipos que hay:

class User < ActiveRecord::Base 

    after_find :preset_types 


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

end 
Cuestiones relacionadas