2010-01-03 3 views
3

J'ai créé une classe Model où je définis des méthodes basées sur une méthode (attribut) appelée dans User (qui hérite de Model). Le problème est que je ne peux pas remplacer la méthode définie par define_method, et appeler super pour passer à la méthode définie. Je suppose que c'est parce que la méthode définie est ajoutée à l'utilisateur lui-même, et non au modèle, donc il n'a en fait pas de méthode dans la superclasse (c'est-à-dire le modèle).Appeler super sur une méthode définie par define_method

La raison pour laquelle je veux faire ceci est parce que la plupart des attributs devraient être sauvés à la base de données directement, tandis que certains attributs, comme le mot de passe, ont besoin de traitement supplémentaire.

class Model 
    def self.attribute(name) 
    define_method(name) do 
     self 
    end 
    end 
end 

class User < Model 
    attribute :password 
end 

class User2 < Model 
    attribute :password 

    def password 
    super 
    end 
end 

@user = User.new 
puts @user.password # => <User:0x00000100845540> 

@user2 = User2.new 
puts @user2.password 
# define_super.rb:17:in `password': super: no superclass method 
# `password' for #<User2:0x00000100845578> (NoMethodError) 
# from define_super.rb:25:in `<main>' 

Y at-il un moyen de changer le code pour que cela fonctionne? J'ai besoin d'un moyen de remplacer les méthodes créées dynamiquement.

Répondre

9

définir la méthode sur la superclass:

class Model 
    def self.attribute(name) 
    superclass.send :define_method, name do 
     self 
    end 
    end 
end 
+0

Merci. C'était juste ce dont j'avais besoin. –

+0

Si c'est ce dont vous aviez besoin, vous devriez sélectionner la réponse. Mieux vaut tard (de plus de 7 ans) que jamais. :-) –

3

La façon dont Rails traite c'est qu'il ya plusieurs façons d'obtenir des attributs. L'un d'eux est (par convention) jamais surchargé donc il peut être utilisé dans vos méthodes définies:

# This method is never overridden, but also rarely used as a public method 
def[](key) 
    # Returns value of `key` attribute 
end 

# This is the effective default implementation of an attribute 
def att1 
    self[:att1] 
end 

# This shows how you can have custom logic but still access the underlying value 
def att2 
    self[:att2] unless self[:att2].empty? 
end 
+0

ou similaire: 'a = Document.last, a.read_attribute (: nom)', vous pouvez aussi faire 'a.write_attribute (: nom, 'fooo')' – equivalent8

Questions connexes