On Tuesday, June 08, 2010 02:33:27 pm Juan Manuel Barreneche wrote:
> Buenas!
> 
> 2010/6/8 Luciano Ruete <[email protected]>
> 
> > Hola lista,
> > 
> > Estoy trabajando con una clase que en parte cuenta bits, esos bits me
> > sirven
> > para luego alimentar una round robin data base[1].
> > 
> > El contador es incrementado periodicamente y llega un punto que supera la
> > capacidad de almacenamiento en la base de datos, en mi caso estoy usando
> > 'integer unsigned' en la migración y MySQL detrás.
> > 
> > No quiero usar numeros más grandes(:limit => xx) ya que no me hace falta,
> > no
> > tengo problemas en, una vez que se llene el entero, resetear el
> > "contador".
> > 
> > Mi problema particular es que cuando paso el límite y hago un save, rails
> > no
> > me avisa del overflow, y simplemente guarda el valor más grande posible
> > para
> > esa variable que en un unsigned int es 4294967295.
> > 
> > Puedo hacer el chequeo a mano(if x > 4294967295) , pero me gustaría que
> > sea algo más prolijo si fuera posible. Buscar en google no me ayudo
> > mucho así que
> > por eso paso por aquí.
>
> Hice la prueba con Rails 2.3.5 y Rails inserta el valor correcto (Al menos
> intenta).
> En el Log se ve lo siguiente:
> INSERT INTO `bws` (`valor`, `created_at`, `updated_at`, `deleted_at`)
> VALUES(2147483648, '2010-06-08 17:24:55', '2010-06-08 17:24:55', NULL)
> 
> Esto en MySql le da un Warning, MySQL graba exitosamente pero trunca. No
> encontré una manera limpia desde Rails de consultar los warnings . Pero si
> encontré lo siguiente:
> ruby-1.9.1-p378 > b = Bw.create :valor => 2147483648
>  => #<Bw id: 20, valor: *2147483648*, created_at: "2010-06-08 17:21:52",
> updated_at: "2010-06-08 17:21:52", deleted_at: nil>
> ruby-1.9.1-p378 > *conn = b.connection.instance_variable_get '@connection'*
>  => #<Mysql:0x8e20ac8>
> ruby-1.9.1-p378 > *res = conn.query('SHOW WARNINGS').fetch_hash*
>  => {"Level"=>"Warning", "Code"=>"1264", "Message"=>"Out of range value for
> column 'valor' at row 1"}
> ruby-1.9.1-p378 > b.reload
>  => #<Bw id: 20, valor: *2147483647*, created_at: "2010-06-08 17:21:52",
> updated_at: "2010-06-08 17:21:52", deleted_at: nil>
> 
> También la raw connection a MySQL (@connection dentro del mySQL Adapter)
> tiene un #warning_count, pero por la manera en que el adapter usa la
> conexión, si consultás ese valor te va a dar cero.
> 
> Personalmente optaría por verificar el límite antes de salvar... y que ese
> límite se pueda configurar en algún YML o algo así...

Fui por ese lado nomás, hice un módulo en /lib para poder sharear el código 
entre las 3 clases que necesitan el check y luego un before_save 
check_integer_overflow que hace el trabajo.
En mi caso es muy básico ya que los atributos que necesitan el check son 
omónimos en todas las clases.

Dejo el código para archivo
en lib/overflow_check.rb:

module OverflowCheck           
  INT_OVERFLOW=4294967295      
  def check_integer_overflow   
    self.attribute_to_check -= INT_OVERFLOW if self.attribute_to_check > 
INT_OVERFLOW
  end
end


Y en el model:

class NeedOverflowCheck < ActiveRecord::Base
  include OverflowCheck        
  before_save :check_integer_overflow
end

Gracias por la ayuda! :)
-- 
Luciano Ruete
_______________________________________________
Ruby mailing list
[email protected]
http://lista.rubyargentina.com.ar/listinfo.cgi/ruby-rubyargentina.com.ar

Responder a