Forum: Rails-ES Sobre BigDecimal y columnas decimal

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
72eaa24da031e3c4931809f27838dabb?d=identicon&s=25 Ricardo Pérez (Guest)
on 2007-01-26 13:13
Las columnas decimal(x,y) en Rails 1.2 se mapean a objetos BigDecimal.
Me parece perfecto, pero hay algo que no me gusta.

Por ejemplo, una columna:

precio decimal(5,2)

de una tabla "articulos" se mapea en un objeto BigDecimal, pero ese
objeto no "recuerda" la precisión ni la escala de la columna
correspondiente.

Por tanto,

articulo = Articulos.find(1)
articulo.precio # este objeto es BigDecimal, pero no se sabe cuántos
decimales debería contener

Lo que significa que "articulo.precio.to_s" no "dibujará" los decimales
que corresponden según la escala de la columna.

Por ejemplo, si en la columna guardamos el valor 5.20, la expresión
"articulo.precio.to_s" devolverá "5.2".

De la misma forma, si guardamos el valor "5", la expresión
"articulo.precio.to_s" devolverá "5.0".

Si el objeto BigDecimal recordara cuántos decimales debe mostrar,
entonces el método to_s podría dar como resultado siempre valores más
apropiados. En el caso del 5.20, devolvería "5.20", y en el caso del 5,
devolvería "5.00". Igualmente, si la columna fuese decimal(5), al
guardar los valores 5.20 y 5, el to_s devolvería siempre "5".

Así además se podría resolver fácilmente el problema que comento en
http://www.ruby-forum.com/topic/95287

¿Cómo se podría implementar ese comportamiento? Soy bastante novato en
Rails, y aunque he buceado por sus ficheros, todavía no he dado con la
tecla.

¿Alguien me ayuda?
B8eb6140a480852282b1deb8f7987a24?d=identicon&s=25 Silvio Quadri (Guest)
on 2007-01-26 17:31
(Received via mailing list)
La verdad es que creo que no hay muchas variantes para esto, mas que
modificar el scaffold generado, convirtiendo el decimal a numerico.


2007/1/26, Ricardo Pérez <ruby-forum-incoming@andreas-s.net>:
C4568275b01d7cd3bde96f212c379bac?d=identicon&s=25 Andrés Cirugeda Esco (Guest)
on 2007-01-26 17:45
(Received via mailing list)
Hola Ricardo

En lugar de dejar que sea .to_s el que pinte el valor has de usar
sprintf para darle el formato exacto que tu quieres. Si lo quieres
siempre con dos decimales sería algo así (te lo digo de memoria, igual
no es exacto, pero va por ahí)

sprintf("%0.02f", articulo.precio)

Para lo que comentas en el post de ruby-forum te sirve lo mismo, de
todas formas allí si las columnas numéricas tienen 0 decimales, lo mejor
es que las definas como integer en lugar de numeric.

Saludos

Ricardo Pérez escribió:
>
> "articulo.precio.to_s" devolverá "5.2".
> Así además se podría resolver fácilmente el problema que comento en
> http://www.ruby-forum.com/topic/95287
>
> ¿Cómo se podría implementar ese comportamiento? Soy bastante novato en
> Rails, y aunque he buceado por sus ficheros, todavía no he dado con la
> tecla.
>
> ¿Alguien me ayuda?
>

--
Andrés Cirugeda Esco
ASPgems
Email: andres at aspgems dot com

'All we have to decide is what to do with the time that is given to us'.
Gandalf.
Aab7643fde6e4efd0177c5ab014928b0?d=identicon&s=25 salvador zalapa (Guest)
on 2007-01-26 18:19
(Received via mailing list)
Disculpen, alguien sabe como adjuntar un pdf a un mail?? Gracias !

_________________________________________________________________
Windows Live Spaces en Prodigy/MSN Spaces: Crea tu propio espacio.
http://spaces.live.com
72eaa24da031e3c4931809f27838dabb?d=identicon&s=25 Ricardo Pérez (Guest)
on 2007-01-26 18:25
Gracias por vuestras respuestas.

En realidad el problema no está en el scaffold, sino más adentro: en el
propio BigDecimal. Mi opinión es que un BigDecimal debería tener un
campo de escala para saber cómo imprimirse correctamente cuando le hagas
un to_s.

He hecho algunas modificaciones en el código base de Rails, y al parecer
he dado con la tecla. Si queréis probarlo vosotros, a continuación os
indico los cambios que hay que hacer:

* en
/activesupport/lib/active_support/core_ext/bigdecimal/formatting.rb,
sustituir el contenido por el siguiente:

class BigDecimal #:nodoc:

  alias :_original_to_s :to_s

  attr_accessor :scale
  @scale = 0

  def to_s(format="F")
    s = _original_to_s(format)
    a = s.split(".")
    if scale and scale != 0
      a[0] + "." + a[1] + "0" * (scale - a[1].length)
    elsif scale and scale == 0
      a[0] + ".0"
    else
      a[0]
    end
  end
end


* en /activerecord/lib/active_record/base.rb, cambiar la definición del
método read_attribute_before_type_cast por el siguiente:

def read_attribute_before_type_cast(attr_name)
  r = @attributes[attr_name]
  column = column_for_attribute(attr_name.to_s)
  if column.type == :decimal and r.respond_to?(:scale=)
    r.scale = column.scale
  end
  r
end


* en
/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb,
cambiar la definición de los métodos type_cast, type_cast_code y
self.value_to_decimal por los siguientes:

def type_cast(value)
  return nil if value.nil?
  case type
    when :string    then value
    when :text      then value
    when :integer   then value.to_i rescue value ? 1 : 0
    when :float     then value.to_f
    when :decimal   then self.class.value_to_decimal(value, scale)
    when :datetime  then self.class.string_to_time(value)
    when :timestamp then self.class.string_to_time(value)
    when :time      then self.class.string_to_dummy_time(value)
    when :date      then self.class.string_to_date(value)
    when :binary    then self.class.binary_to_string(value)
    when :boolean   then self.class.value_to_boolean(value)
    else value
  end
end

def type_cast_code(var_name)
  case type
    when :string    then nil
    when :text      then nil
    when :integer   then "(#{var_name}.to_i rescue #{var_name} ? 1 : 0)"
    when :float     then "#{var_name}.to_f"
    when :decimal   then
"#{self.class.name}.value_to_decimal(#{var_name}, #{scale})"
    when :datetime  then
"#{self.class.name}.string_to_time(#{var_name})"
    when :timestamp then
"#{self.class.name}.string_to_time(#{var_name})"
    when :time      then
"#{self.class.name}.string_to_dummy_time(#{var_name})"
    when :date      then
"#{self.class.name}.string_to_date(#{var_name})"
    when :binary    then
"#{self.class.name}.binary_to_string(#{var_name})"
    when :boolean   then
"#{self.class.name}.value_to_boolean(#{var_name})"
    else nil
  end
end

def self.value_to_decimal(value, scale=nil)
  if value.is_a?(BigDecimal)
    r = value
  elsif value.respond_to?(:to_d)
    r = value.to_d
  else
    r = value.to_s.to_d
  end
  r.scale = scale
  r
end


Todos estos cambios consiguen que un BigDecimal proveniente de una
columna decimal(x,y) contenga dentro un atributo llamado "scale" con el
valor "y". Y cuando se le pida que se imprima con el to_s, éste tiene en
cuenta el valor de escala.

Lo he probado con el scaffold y con el script/console, y parece que
funciona decentemente (a falta de hacer más pruebas). ¿Qué os parece?
Aab7643fde6e4efd0177c5ab014928b0?d=identicon&s=25 salvador zalapa (Guest)
on 2007-01-26 19:11
(Received via mailing list)
Hola de nuevo, bueno creo que asi fue la solución, pero tengo el problema q
por ejemplo yahoo, lo recibo como .bin, alguien sabe como se hace esto?

attachment :content_type =>'aplpication/pdf',
        :body => File.read("prueba.pdf")


>Windows Live Spaces en Prodigy/MSN Spaces: Crea tu propio espacio.
>http://spaces.live.com
>
>_______________________________________________
>Ror-es mailing list
>Ror-es@lists.simplelogica.net
>http://lists.simplelogica.net/mailman/listinfo/ror-es

_________________________________________________________________
Live Search en Prodigy/MSN. Todo lo que buscas ahora más rapido
http://live.com
7775c52990f93fbe652398e2c486df46?d=identicon&s=25 Jairo Enrique Serrano Castañeda (Guest)
on 2007-01-29 11:51
(Received via mailing list)
no te estaras equivocando en el tipo?

aplpication/pdf

y debe ser..

application/pdf

? o solo es de
transcripción?On 1/26/07, salvador zalapa <szalapa@hotmail.com> wrote:
> >To: ror-es@lists.simplelogica.net
> >Ror-es mailing list
> http://lists.simplelogica.net/mailman/listinfo/ror-es
>


--
Jairo Enrique Serrano Castañeda
Estudiante de Maestría en Software Libre
Ingeniero de Sistemas UTB
T - http://www.jsnat.com - http://savio.unitecnologica.edu.co
C - http://www.drupal.org.es - http://www.champetux.org
This topic is locked and can not be replied to.