setters - ¿Cuál es la forma correcta de anular un método setter en Ruby on Rails?
setters ruby (5)
Estoy usando Ruby on Rails 3.2.2 y me gustaría saber si la siguiente es una manera "correcta" / "correcta" / "segura" de anular un método setter para un atributo de mi clase.
attr_accessible :attribute_name
def attribute_name=(value)
... # Some custom operation.
self[:attribute_name] = value
end
El código anterior parece funcionar como se esperaba. Sin embargo, me gustaría saber si, usando el código anterior, en el futuro tendré problemas o, al menos, qué problemas "debería esperar" / "podría pasar" con Ruby on Rails . Si esa no es la manera correcta de anular un método setter, ¿cuál es la forma correcta?
Nota : si uso el código
attr_accessible :attribute_name
def attribute_name=(value)
... # Some custom operation.
self.attribute_name = value
end
Obtuve el siguiente error:
SystemStackError (stack level too deep):
actionpack (3.2.2) lib/action_dispatch/middleware/reloader.rb:70
Descubrí que (al menos para las colecciones de relaciones ActiveRecord) funciona el siguiente patrón:
has_many :specialties
def specialty_ids=(values)
super values.uniq.first(3)
end
(Esto toma las primeras 3 entradas no duplicadas en el conjunto pasado).
Usar attr_writer
para sobrescribir setter attr_writer: attribute_name
def attribute_name=(value)
# manipulate value
# then send result to the default setter
super(result)
end
Use la palabra clave super
:
def attribute_name=(value)
super(value.some_custom_encode)
end
Por el contrario, para anular al lector:
def attribute_name
super.some_custom_decode
end
=============================================== ====================== Actualización: 19 de julio de 2017
Ahora la documentación de Rails también sugiere usar super
como esta:
class Model < ActiveRecord::Base
def attribute_name=(value)
# custom actions
###
super(value)
end
end
=============================================== ======================
Respuesta original
Si desea sobrescribir los métodos de configuración para las columnas de una tabla mientras se accede a través de los modelos, esta es la manera de hacerlo.
class Model < ActiveRecord::Base
attr_accessible :attribute_name
def attribute_name=(value)
# custom actions
###
write_attribute(:attribute_name, value)
# this is same as self[:attribute_name] = value
end
end
Consulte Anulación de los accesos predeterminados en la documentación de Rails.
Por lo tanto, su primer método es la forma correcta de anular los establecedores de columnas en Modelos de Ruby on Rails. Rails ya proporcionan estos accesos para acceder a las columnas de la tabla como atributos del modelo. Esto es lo que llamamos mapeo ORM de ActiveRecord.
También tenga en cuenta que attr_accessible
en la parte superior del modelo no tiene nada que ver con los attr_accessible
acceso. Tiene una función completamente diferente (ver esta pregunta )
Pero en Ruby puro, si ha definido los descriptores de acceso para una clase y desea anular el setter, debe hacer uso de una variable de instancia como esta:
class Person
attr_accessor :name
end
class NewPerson < Person
def name=(value)
# do something
@name = value
end
end
Esto será más fácil de entender una vez que sepa lo que attr_accessor
hace. El código attr_accessor :name
es equivalente a estos dos métodos (getter y setter)
def name # getter
@name
end
def name=(value) # setter
@name = value
end
También su segundo método falla porque causará un bucle infinito ya que está llamando al mismo método attribute_name=
dentro de ese método.
En rieles 4
Digamos que tienes un atributo de edad en tu mesa
def age=(dob)
now = Time.now.utc.to_date
age = now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
super(age) #must add this otherwise you need to add this thing and place the value which you want to save.
end
Nota: Para las nuevas esquinas en rieles 4 no es necesario especificar attr_accessible en el modelo. En su lugar, debe poner en una lista blanca sus atributos en el nivel de controlador utilizando el método de permiso .