internacionalización de importes entrados

Hola,

No he encontrado ninguna solución que me agrade al problema de entrar
valores numéricos en RoR, en diferentes formatos.

La gran diferencia está en los separadores de decimales y miles.

ES: 1.254,09
US: 1,254.09

He creado formatos por defecto y cualquier importe con .to_s sale en el
formato deseado, el problema lo tengo cuando recbio estos números por
parte del usuario, no he encontrado la manera que RoR haga la
transformación automáticamente, es decir, si el usuario entra 1254,09
RoR usa el valor 1254.00

Para que me funcione correctamente, he de cambiar cada valor uno por
uno, por ejemplo:

def convert_european_number(value)

value=value.gsub('.','')
return value.to_s.gsub(',', '.').to_f

end

he mirado la documentación de i18N pero únicamente sirve para display,
no para entrar importes …

si esta es la única manera de hacerlo, ¿ alguna idea, indicación, … de
cómo hacerlo lo más fácilmente posible ?

gracias por vuestra ayuda!

r.

Hola Raimon,

A mi se me ocurre a sí a votepronto, que descompongas el campo de
entrada en dos (cifra sín céntimos - céntimos) y entre medio pongas la
“,” o el “.” en función del idioma. Luego juntas los dos datos en uno
antes de cargarlo en la tabla. Y claro, eso sí, validas que no mentan
ni comas ni puntos en ambos campos.

Suerte.

El día 4 de mayo de 2009 11:25, Raimon Fs
[email protected]
escribió:> He creado formatos por defecto y cualquier importe con .to_s sale en el

value=value.gsub(‘.’,‘’)

gracias por vuestra ayuda!

r.

Posted via http://www.ruby-forum.com/.


Ror-es mailing list
[email protected]
http://lists.simplelogica.net/mailman/listinfo/ror-es


Fernando V.
Web Designer
http://www.fernandoval.es

Lo veo complicado, luego hay un montón de cálculos con estos campos y
sería demasiado complicado.

Creo que se me escapa algo, porque no he visto mucho movimiento sobre
este tema, y me preocupa por dos cosas:

  1. que cada vez me cuesta pillar más las cosas porque me hago viejo :slight_smile:

  2. o que nadie excepto los que usan formato numérico usan RoR

En el forum inglés tampoco obtuve ninguna respuesta que me gustara,
simplemente tenía que alterar cada valor de cada campo numérico (float)
del europeo al inglés, para que RoR no se quejara al guardar el valor
numérico en la base de datos …

Entiendo que haya que analizar bien la manera de entrar los valores,
pues uno nunca sabe qué es lo que el usuario entra pero seguro que tiene
que haber una manera más fácil …

¿ alguien que me ilumine, por favor ?

muchas gracias!

r.

De todos modos, la lista lleva unos días un poco parada. Yo tengo un
post al que aún no me ha respondiodo nadie, así que habrá que tener
paciencia…
(es el del “acts_a_tree”)
Suerte, yo seguiré buscando guía y orientación… :slight_smile:

Ah, y no te preocupes, no eres el único que se hace viejo… :wink:

Un saludo.

El día 4 de mayo de 2009 17:41, Raimon Fs
[email protected]
escribió:>

muchas gracias!

r.

Posted via http://www.ruby-forum.com/.


Ror-es mailing list
[email protected]
http://lists.simplelogica.net/mailman/listinfo/ror-es


Fernando V.
Web Designer
http://www.fernandoval.es

Creo que no me he explicado bien ahora que lo estaba leyendo …

Lo que me interesaría sería cambiar el formato/valor del valor entrado
por el usuario antes de que RoR lo asocie al objeto de ActiveRecord.

Si el campo fuerta string, no habría problema, pues el valor que el
usuario ha entrado es el mismo que está en RoR, pero en un campo
numérico float, RoR ya le cambia el valor cuando yo hago:

@expedient=Expedient.new(params[:expedient])

Actualmente lo que hago es cambiar el valor de los campos que hay en el
array params, pero tengo que acordarme de hacerlo en Update, Create, y
alguno que otro sitio, y el principio de DRY se rompe, y hace la
aplicación más compleja.

Quería llevar estos cambios al Modelo, usar before_validation_on_create
pero cuando examino los valores, RoR ya los ha adaptado a su manera, y
el valor 1245,09 se ha transformado en 1245.00

¿ Cómo lo estás haciendo vosotros ?

¿ todos usáis formatos americanos ?

¿ se me escapa algo de I18n ?

gracias …

salu2,

r.

Precisamente por eso te proponía descomponerlo, porque he leído en
varios sitios que el float tiene sus peligros con los redondeos. Creo
que lo comentan en el libro “Agile Web D…” al crear la
aplicación Depot.

Pero si no puedes, habrá que buscar otra
solución.

El día 4 de mayo de 2009 18:29, Fernando [email protected]
escribió:>

¿ alguien que me ilumine, por favor ?


Fernando V.
Web Designer
http://www.fernandoval.es


Fernando V.
Web Designer
http://www.fernandoval.es

Buenas,
puedes probar a usar el método <nombre_atributo>_before_type_cast para
acceder al atributo antes de que se haya la conversión de cara a
guardarlo
en la base de datos:

http://rails.noobkit.com/show/ruby/rails/rails-stable/activerecord/activerecord/base.html

saludos

2009/5/4 Raimon Fs [email protected]

Borja Martín wrote:

Buenas,
puedes probar a usar el método <nombre_atributo>_before_type_cast para
acceder al atributo antes de que se haya la conversión de cara a
guardarlo
en la base de datos:

http://rails.noobkit.com/show/ruby/rails/rails-stable/activerecord/activerecord/base.html

esto me ha ido perfecto !!!

:slight_smile:

mira que leo, leo, leo, … y siempre hay algo nuevo …

gracias por la información …

he creado en el modelo:

def before_validation
numbers_validations
end


def numbers_validations

self.capital_total= 

capital_total_before_type_cast.gsub(‘,’,‘.’).to_f if
capital_total_before_type_cast != nil

end

y por las pruebas que he hecho, funciona a las mil maravillas …

es una lástima que no coja directamente la información de la
configuración local, pero bueno, menos da una piedra …

:slight_smile:

salu2 y gracias de nuevo …

r.

2009/5/4 Raimon Fs [email protected]:

Si el campo fuerta string, no habría problema, pues el valor que el
usuario ha entrado es el mismo que está en RoR, pero en un campo
numérico float

Si es para almacenar importes y vas a manejar céntimos te recomiendo
usar enteros y no floats para almacenarlos en la base de datos.

Raul M. wrote:

2009/5/4 Raimon Fs [email protected]:

Si el campo fuerta string, no habr�a problema, pues el valor que el
usuario ha entrado es el mismo que est� en RoR, pero en un campo
num�rico float

Si es para almacenar importes y vas a manejar c�ntimos te recomiendo
usar enteros y no floats para almacenarlos en la base de datos.

Uso BigDecimal (Numeric with precission)

salu2,

r.

Raimon Fs dijo [Mon, May 04, 2009 at 07:02:15PM +0200]:

  capital_total_before_type_cast != nil


end

Te sugiero ser un poco más precavido… Si tus usuarios te pueden
escribir, por ejemplo, tanto 1.234,56 como 1,234.56, ¿no deberías
poder reconocer a ambos? Bueno… Por simplicidad, permíteme asumir
que estás hablando de dinero, por lo que puedes tener hasta dos
posiciones después del punto (o coma) decimal:

def numbers_validations
self.capital_total = capital_total_before_type_cast.
gsub(/,./, ‘’).
gsub(/,.$/) {|s| ‘.’ + $1};
end

Saludos,


Gunnar W. - [email protected] - (+52-55)5623-0154 / 1451-2244
PGP key 1024D/8BB527AF 2001-10-23
Fingerprint: 0C79 D2D1 2C4E 9CE4 5973 F800 D80E F35A 8BB5 27AF

Hola,

Yo hace tiempo estuve buscando algo parecido, pero no encontré nada.
Además sabiendo como son los usuarios hay que controlar que no te puedan
escribir cualquier carácter no relacionado con un importe, por eso
también utilizaré funciones javascript para controlar la entrada de
datos.

Salu2.

Gunnar W. wrote:

Raimon Fs dijo [Mon, May 04, 2009 at 07:02:15PM +0200]:

  capital_total_before_type_cast != nil


end

Te sugiero ser un poco más precavido… Si tus usuarios te pueden
escribir, por ejemplo, tanto 1.234,56 como 1,234.56, ¿no deberías
poder reconocer a ambos? Bueno… Por simplicidad, permíteme asumir
que estás hablando de dinero, por lo que puedes tener hasta dos
posiciones después del punto (o coma) decimal:

def numbers_validations
self.capital_total = capital_total_before_type_cast.
gsub(/,./, ‘’).
gsub(/,.$/) {|s| ‘.’ + $1};
end

Hola,

Sí, tienes razón, pero para mi lo importante era donde poner el código
para interceptar los valores, y luego adaptarlo a las necesidades.

Quería hacerlo también teniendo en cuenta la configuración del locale
activado, pero al final, los usuarios escriben lo que les da la gana, o
sea que lo que tengo que hacer es adaptarlo a lo que la base de datos
quiere …

gracias por el ejemplo!

salu2,

r.

Raimon Fs dijo [Tue, May 05, 2009 at 08:12:42AM +0200]:

Quería hacerlo también teniendo en cuenta la configuración del locale
activado, pero al final, los usuarios escriben lo que les da la gana, o
sea que lo que tengo que hacer es adaptarlo a lo que la base de datos
quiere …

gracias por el ejemplo!

Jé, hasta me la pones más fácil - Si quieres descartar cualquier
caracter no numérico excepto por el último (si es que éste es un punto
o una coma):

capital_total_before_type_cast.gsub(/,/, ‘.’).gsub(/[^\d.]/,
‘’).gsub(/.(?=.+.)/,’’)

Tres expresiones regulares. La primera, pensando en los españoles que
hacen todo al revés :wink: convierte a todas las comas en puntos (para
tener un punto decimal como tu_deidad_favorita manda). La segunda,
descarta todos los caracteres excepto los dígitos numéricos y el
punto. Y como puedes tener más de un punto en tu cadena, la tercer
expresión elimina a cualquier punto que no sea el último de la cadena.

orig = ‘1 234,56_78.90,01’
=> “1 234,56_78.90,01”

limpio = orig.gsub(/,/, ‘.’).gsub(/[^\d.]/, ‘’).gsub(/.(?=.+.)/, ‘’)
=> “1234567890.01”

limpio.to_f
=> 1234567890.01

Saludos,


Gunnar W. - [email protected] - (+52-55)5623-0154 / 1451-2244
PGP key 1024D/8BB527AF 2001-10-23
Fingerprint: 0C79 D2D1 2C4E 9CE4 5973 F800 D80E F35A 8BB5 27AF

Gunnar W. wrote:

Raimon Fs dijo [Tue, May 05, 2009 at 08:12:42AM +0200]:

Quería hacerlo también teniendo en cuenta la configuración del locale
activado, pero al final, los usuarios escriben lo que les da la gana, o
sea que lo que tengo que hacer es adaptarlo a lo que la base de datos
quiere …

gracias por el ejemplo!

Jé, hasta me la pones más fácil - Si quieres descartar cualquier
caracter no numérico excepto por el último (si es que éste es un punto
o una coma):

capital_total_before_type_cast.gsub(/,/, ‘.’).gsub(/[^\d.]/,
‘’).gsub(/.(?=.+.)/,’’)

gracias de nuevo …

pero sigo con la mosca detrás de la oreja …

¿ no hay ninguna manera de hacerlo mejor ?

estaría bien poder usar sólo
@dispo=Disposicion.new(params[:disposicion]) y que él solito hiciera el
resto en los campos BigDecimal, sin tener luego que hacer un nuevo cast
y poner el valor correcto en los atributos que RoR ha puesto mal, todo
esto antes de la validación …

gracias de nuevo …

r.

Raimon Fs dijo [Tue, May 05, 2009 at 05:44:31PM +0200]:

‘.’).gsub(/[^\d.]/, ‘’).gsub(/.(?=.+.)/,’’)
self. capital_inicial= capital_inicial_before_type_cast.gsub(/,/,
‘.’).gsub(/[^\d.]/, ‘’).gsub(/.(?=.+.)/,’’)

1- DRY. Si vas a repetir las regexes, mejor sácalas a un método.

private
def limpia_numero(entrada)
entrada.gsub(/,/, ‘.’).gsub(/[^\d.]/, ‘’).gsub(/.(?=.+.)/,’’)
end

2- Si son dos o tres atributos, no hay mayor problema, puedes ponelos
explícitamente - ya queda más legible:

self.capital_total = limpia_numero(capital_total_before_type_cast)
self.capital_inicial =
limpia_numero(capital_inicial_before_type_cast)

Sin embargo, puedes…

%w(capital_total capital_inicial).each do |campo|
self.send(campo) = limpia_numero(eval("#{campo}_before_type_cast"))
end

Saludos,


Gunnar W. - [email protected] - (+52-55)5623-0154 / 1451-2244
PGP key 1024D/8BB527AF 2001-10-23
Fingerprint: 0C79 D2D1 2C4E 9CE4 5973 F800 D80E F35A 8BB5 27AF

Raimon Fs wrote:

Gunnar W. wrote:

Raimon Fs dijo [Tue, May 05, 2009 at 08:12:42AM +0200]:

Quería hacerlo también teniendo en cuenta la configuración del locale
activado, pero al final, los usuarios escriben lo que les da la gana, o
sea que lo que tengo que hacer es adaptarlo a lo que la base de datos
quiere …

gracias por el ejemplo!

Jé, hasta me la pones más fácil - Si quieres descartar cualquier
caracter no numérico excepto por el último (si es que éste es un punto
o una coma):

capital_total_before_type_cast.gsub(/,/, ‘.’).gsub(/[^\d.]/,
‘’).gsub(/.(?=.+.)/,’’)

y para rizar el rizo …

lo mismo pero en vez de un atributo, unos 20 …

no vamos a escribir lo mismo para 20, alguna manera más fácil ?

en otros lenguajes usaría un Pointer y listo, pero aquí no lo tengo
claro aún, investigaré un poco a ver …

self. capital_total =capital_total_before_type_cast.gsub(/,/,
‘.’).gsub(/[^\d.]/, ‘’).gsub(/.(?=.+.)/,’’)
self. capital_inicial= capital_inicial_before_type_cast.gsub(/,/,
‘.’).gsub(/[^\d.]/, ‘’).gsub(/.(?=.+.)/,’’)

salu2,

r.

ok, gracias por la info!

salu2,

r.