Y, la solución obvia—y correcta—es la que vos terminaste haciendo.
Migrá la base de datos y hacé la columna not null y con default 0.

def self.up
  change_column :movements, :debit, :integer, :null => false, :default => 0
  change_column :movements, :credit, :integer, :null => false, :default => 0
end

Ahí pasa a funcionar solo :)

Si no, la siguiente mejor solución (si no podés tocar la base de
datos, por ejemplo), es decirle a rails que el campo ese siempre sea
un integer, sin importar el valor en la base de datos:

class ClientMovement < ActiveRecord::Base
  def debit
    read_attribute(:debit).to_i
  end
end

Y seguiría funcionando transparentemente -- movements.sum(&:debit)
devolvería lo que querés sin necesidad de hacer nada en la vista.

Pero ta, si el cambio pasa en la base, mucho mejor.

Hacer el casteo o filtrado en las vistas cada vez que necesitás el
valor es una grosería :)

Sobre el query en sí, ActiveRecord te da un API "relativamente"
elegante (según cómo se lo mire) para no tener que escribir SQL a
mano. En particular, lo que vos querés, es hacer JOIN con un par de
tablas y filtrar por una condición, y quedaría así:

ClientMovement.all(:joins => [:inquiry, :client], :conditions => {
"clients.id" => params[:id] })

Entre otras cosas, esto te evita el SQL injection que te mencionaron,
y es mucho más fácil de leer. (El valor de :joins asume que
ClientMovement tiene una asociación "belongs_to :client" y "belongs_to
:inquiry". En caso de que fueran has_many, lo que le pasás es el
nombre de la asociación, por lo que sería :joins => [:inquiries,
:clients])

Y finalmente, habrás visto que los ejemplos de código los escribo en
inglés. Cada vez que alguien mezcla idiomas distintos en código, se
muere un gatito. Vos no querés que se mueran gatitos, verdad?

POR FAVOR, ESCRIBAN EL CÓDIGO EN UN SÓLO IDIOMA.

O hacen un interprete de ruby donde las palabras clave y constantes,
etc están en español (clase Arreglo < Objeto; fin), o escriben todo el
código en inglés. Pero es horriblemente molesto leer código en idiomas
mezclados.

Saludos,
-foca

PD: Mirá la documentación de ActiveRecord::Base#read_attribute (y ya
que estás, write_attribute) para entender cómo funciona la segunda
solución. Y la de ActiveRecord::Base.find para ver las opciones qué le
podés pasar, así no tenés que hacer find_by_sql.


2010/2/22 Nestor Rodriguez <[email protected]>:
> Hola gente, como andan, aqui peleandome con el array, estoy tratando de
> hacer un sistema de cuentas corrientes y estoy con eso del DEBITO Y EL
> CREDITO, así que necesito mostrar el ESTADO DE CUENTAS de un cliente, por lo
> tanto en el CONTROLADOR escribo esto:
>
> @clientes_movimientos = ClienteMovimiento.find_by_sql("Select
> clientes_movimientos.* " +
>                    "from clientes_movimientos, solicitudes, clientes " +
>                    "where clientes_movimientos.solicitud_id = solicitudes.id
> and " +
>                    " solicitudes.cliente_id = clientes.id and " +
>                    " clientes.id = #{params[:id]}")
> AQUÍ NO ESTA EL PROBLEMA, el problema es que en el array que me genera,
> vienen dos campos, DEBITO y CREDITO, que quiero sumarlos (cada uno un su
> columna) para mostrar los totales algo así como:
>
> fec mov         Concepto        Debito          Credito         Fec
> vencimiento         Num cuota Observacion
> 22/02/2010      Cuota   300,000                 02/02/2010      1/4
> debito automatico
> 22/02/2010      Cuota   200,000                 02/04/2010      2/4
> debito automatico
> 22/02/2010      Cuota   200,000                 02/05/2010      3/4
> debito automatico
> 22/02/2010      Cuota   200,000                 02/06/2010      4/4
> debito automatico
> TOTAL                                  1,000,000             0
>
> Lo que pasa es que el campo CREDITO, como no se le cargo nada tiene valores
> nulos, ahora bien mi pregunta es la siguiente:
> Como le digo a un bloque, que si es nulo el campo, lo tome como 0 (cero).
> Algo así como
>
> @clientes_movimientos.sum {|cm| ifnull(cm.debito,0)}
> @clientes_movimientos.sum {|cm| ifnull(cm.credito,0)}
>
> Obviamente la funcion ifnull no es de ruby que yo sepa. Pero cuando le
> coloco de la forma que aprendí es decir así:
> @clientes_movimientos.sum  {|cm| cm.debito}
> @clientes_movimientos.sum {|cm| cm.credito}
>
> Me lanza un error ya que cm.credito es nulo y no lo puede sumar.
>
> Alguien sabe una función que transforme un valor nulo aquí en por ejemplo 0
> (cero).
>
> Desde ya gracias...
>
> Néstor R.
>
>
>
> _______________________________________________
> Ruby mailing list
> [email protected]
> http://lista.rubyargentina.com.ar/listinfo.cgi/ruby-rubyargentina.com.ar
>
_______________________________________________
Ruby mailing list
[email protected]
http://lista.rubyargentina.com.ar/listinfo.cgi/ruby-rubyargentina.com.ar

Responder a