2010-10-03 2 views
2

Dans le cadre de l'apprentissage de ruby ​​/ rails, j'essaie d'implémenter http://github.com/professionalnerd/simple-private-messages dans mon application à partir de zéro, au lieu de simplement installer le plugin. (Je sais, me causant des problèmes mais c'est une bonne expérience d'apprentissage.)Interrogation des méthodes dans ruby ​​on rails - méthode non définie `read 'pour

J'ai créé le modèle, et les associations semblent correctes et je peux créer de nouveaux messages très bien et ils apparaissent dans la boîte aux lettres des destinataires. Mais si je clique pour voir un message (appelle la méthode d'exposition dans le contrôleur de message) il se déclenche en cherchant une méthode appelée «lire» par exemple.

undefined method `read' for #<Class:0xb6f9ef78> 

Où dois-je mettre la méthode 'read'. Dans private_messages_extensions.rb (la source de plug-in), il a:

module ClassMethods 
    # Ensures the passed user is either the sender or the recipient then returns the message. 
    # If the reader is the recipient and the message has yet not been read, it marks the read_at timestamp. 
    def read(id, reader) 
     message = find(id, :conditions => ["sender_id = ? OR recipient_id = ?", reader, reader]) 
     if message.read_at.nil? && reader == message.recipient 
     message.read_at = Time.now 
     message.save! 
     end 
     message 
    end 
    end 

    module InstanceMethods 
    # Returns true or false value based on whether the a message has been read by it's recipient. 
    def read? 
     self.read_at.nil? ? false : true 
    end 

Quelle est la relation entre les méthodes de classe et méthodes Instance en matière d'insérer directement dans mon propre contrôleur des messages modèle &? Je pensais que j'ai inséré

def read(id, reader) 
... 
end 

dans le modèle, mais le lire? méthode dans la section des méthodes d'instance du code plugin me confond et je continue d'obtenir l'erreur sur l'affichage d'un message.

Aide appréciée!

Répondre

0

classmethods/InstanceMethods est une technique standard Ruby qui est basée sur ce code:

def self.included(base) 
    base.extend ClassMethods 
    base.include InstanceMethods 
end 

que vous (à peu près) trouver dans l'original code. D'ailleurs il y a la préoccupation de ActiveSupport qui peut simplifier le code ci-dessus (jetez un coup d'oeil dans la documentation pour plus d'informations)

Ainsi, chaque fois que le module est inclus dans la classe alors toutes les méthodes dans le module de classmethods seront devenus méthodes classe de la classe cible et toutes les méthodes dans InstanceMethods deviendront des méthodes d'instance de la classe cible.

Ainsi, votre méthode est read méthode de classe, qui doit être appelé comme:

m = MyModel.new 
m.read?   # => ok, it is an instance method 
MyModel.read  # => ok, it is a class method 
m.read   # => oops, WRONG! FAILURE! 
       # You are calling class method through object 

règles méta-programmation!

Si vous réécrivez le code sans méta chose, vous devriez l'écrire comme:

class MyModel 
    def self.read 
    end 

    def read? 
    end 

end  
+0

Merci pour la réponse très complète! – Dave

0

Je ne l'ai pas regardé le plug-in, mais sur la base des normes d'autres plug-ins, je pense que vous avez besoin de quelque chose comme ceci:

def self.read(id, reader) 
    ... 
end 

Ce qu'il fera une méthode de classe, accessible par appeler User.read.

(je suppose cela à cause du bloc module ClassMethods)

Questions connexes