Self[:field]


#1

Hola,
tenía una duda a ver si me pueden, me apoyo en este ejemplo:

def full_name
[first_name, last_name].join(" ").titleize
end

def full_name=(name)
split = name.split(’ ', 2)
self.first_name = split[0]
self.last_name = split[1]
end

De igual forma, imaginemos que tengo un campo distance (que si existe en
la db), el usuario me da la distancia en kilómetros y yo la guardo en
metros:

def distance=(value)
write_attribute(:distance, value.to_f * 1000))
end

Ahora quiero que cuando el usuario edite, no mostrarle el valor en
metros sino en kilómetros. He probado con:

def distance
self[:distance] / 1000
end

Pero no me funciona. Como si no existiera esta función.

¿Alguna idea?


#2

Hola,

no se si habrá sido un error al escribirlo aquí, pero el
write_attribute lo cierras con dos parentesis.

def distance=(value)
write_attribute(:distance, value.to_f * 1000))
end


#3

Hola
Por qué no hacés una especie de atributo virtual, tal vez
*distance_in_kilometers:

def distance_in_kilometers=(value)
self.distance = value.to_f * 1000
end*
*

def distance_in_kilometers
self.distance / 1000
end*
*
2008/11/12 Tomás Arcos removed_email_address@domain.invalid


#4

Porque quiero que cuando el usuario edite, el campo distance tiene la
distancia tal y como la introdujo, en kilómetros, y no en metros.


#5

Sí, es una errata al escribirlo a mano.

Gracias.


#6

Se podría utilizar un before_find; aunque tu código debería de
funcionar.

Un saludo.


#7

Está bién, pero vos en el form:

en lugar de usar:

<% form_for @foo do |f| %>
<%= f.text_field :distance %>

<% end %>

podrías usar:

<% form_for @foo do |f| %>
<%= f.text_field *:distance_in_kilometers *%>

<% end %>

2008/11/12 Tomás Arcos removed_email_address@domain.invalid


#8

Y ya que usas write_attribute ¿no te sirve read_attribute?


#9

2008/11/12 Tomás Arcos removed_email_address@domain.invalid:

Por consola, funciona perfectamente, es decir, que si meto 1 kilómetro,
en la base de datos se guarda 1000 y cuando hago:

t.distance
=> 1

Correcto. El problema está cuando el usuario hace el edit por
formulario, le sale 1000 en vez de 1 en el campo de texto. Ahora si que
no enciendo nada de nada.

Es curioso, Rails utiliza “value_before_type_cast” como valor del
campo de texto, por eso ves el 1000 en vez del 1. La forma de
arreglarlo sería la siguiente:

<%= f.text_field :distance, :value => @modelo.distance %>

Es un poco pesadez, pero eso parece que lo arregla. Ahora tendriamos
que descubrir porqué los desarrolladores de Rails utilizan justo en
ese punto value_before_type_cast.

Suerte.


#10

2008/11/13 Daniel R. Troitiño removed_email_address@domain.invalid:

Es un poco pesadez, pero eso parece que lo arregla. Ahora tendriamos
que descubrir porqué los desarrolladores de Rails utilizan justo en
ese punto value_before_type_cast.

Y aquí está: http://dev.rubyonrails.org/ticket/6908

Parece ser que en tu caso, si alguien introduce letras en el campo de
texto puedes obtener un valor de 0 u otro, sin aviso para el usuario
(incluso teniendo un validates_numericality_of).

Este código parece que funciona correctamente:


validates_numericality_of :distance

def distance=(value)
value_f = Float(value)
rescue ArgumentError => e
self[:distance] = value
else
self[:distance] = value_f * 1000
end

def distance
value = distance_before_type_cast
value_f = Integer(value)
rescue ArgumentError => e
value
else
value_f / 1000
end

Si el usuario introduce alguna letra en el campo se le devolverá a la
pantalla de edición con la letra donde la escribió. En otro caso el
valor se guarda multiplicado por mil, y cuando se devuelve se devuelve
dividido entre mil (por supuesto tienes que utilizar también la opción
:value cuando dibujes el text_field).

Incluye un par de pruebas, un par de comentarios advirtiendo porque
haces esas cosas tan “raras” y listo.

Suerte.


#11

Creo que he averiguado algo:

def distance=(value)
write_attribute(:distance, value.to_f * 1000))
end

def distance
read_attribute(:distance) / 1000
end

Por consola, funciona perfectamente, es decir, que si meto 1 kilómetro,
en la base de datos se guarda 1000 y cuando hago:

t.distance
=> 1

Correcto. El problema está cuando el usuario hace el edit por
formulario, le sale 1000 en vez de 1 en el campo de texto. Ahora si que
no enciendo nada de nada.