what setters attr_accessor ruby-on-rails ruby ruby-on-rails-3 override setter

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 .