2011-09-05 7 views
12

¿Hay alguna manera de anular un setter o un getter para un modelo en Mongoid? Algo así como:Reemplaza los ajustadores y getters de un modelo Mongoid

class Project 
    include Mongoid::Document 
    field :name, :type => String 
    field :num_users, type: Integer, default: 0 
    key :name 
    has_and_belongs_to_many :users, class_name: "User", inverse_of: :projects 

    # This will not work 
    def name=(projectname) 
    @name = projectname.capitalize 
    end 
end 

donde el método name se puede sobrescribir sin utilizar campos virtuales?

+0

relacionados: http://stackoverflow.com/questions/6699503/mongoid-custom-setters-getters-and-super – marcgg

Respuesta

16
def name=(projectname) 
    self[:name] = projectname.capitalize 
end 
+1

@ user923636 no puede cambiar el campo "_id" de un documento una vez creado. Entonces, si el nombre del proyecto cambia, deberá eliminar el documento anterior y crear uno nuevo con el nombre cambiado. – rubish

23

mejor uso

def name=(projectname) 
    super(projectname.capitalize) 
end 

el método

self[:name] = projectname.capitalize 

puede ser peligroso, causa una sobrecarga con él puede causar la repetición sin fin

+1

gracias obtuve la recursividad del yo [: nombre]. super works – GTDev

+0

@GearHead También he cambiado a super over time (se ve mejor), aunque todavía partes de mi código usan la notación self [: name] y no han enfrentado ninguna recurrencia hasta ahora. – rubish

+2

¿Cómo podría 'super' funcionar si no hay una súper clase? 'Mongoid :: Document' está incluido como Módulo, estoy confundido aquí ... – tothemario

1

tuve un problema similar con la necesidad de reemplazar el setter "usuario" para una relación belongs_to: user. Se me ocurrió esta solución no solo para este caso sino también para envolver cualquier método ya definido dentro de la misma clase.

class Class 
    def wrap_method(name, &block) 
    existing = self.instance_method(name) 

    define_method name do |*args| 
     instance_exec(*args, existing ? existing.bind(self) : nil, &block) 
    end 
end 

Esto le permite hacer lo siguiente en la clase del modelo:

wrap_method :user= do |value, wrapped| 
    wrapped.call(value) 
    #additional logic here 
end 
+0

Exactamente lo que estaba buscando, y buena solución. +1 – user2398029

+0

No intente reinventar la bicicleta. Usa alias_method_chain para esto. – sandrew

+0

gracias por esto! También tiene problemas con los que establecen la relación y los que la obtienen. El comentario de sandrew me hizo buscar en a_m_c's y aprendí acerca de Module # prepend de Ruby 2.0. Gran solución y muy limpia - http://dev.af83.com/2012/10/19/ruby-2-0-module-prepend.html –

Cuestiones relacionadas