2010-01-18 2 views
2

Je suis nouveau à Ruby et travaille à travers quelques tutoriels/screencasts. J'ai atteint la section où ils discutent le rappel before_filter, et il utilise une syntaxe un peu bizarre pour moi. Je ne sais pas si c'est une caractéristique de ruby, si c'est de la magie des rails, et j'espérais que quelqu'un ici pourrait me redresser ou me pointer dans la bonne direction w/r/t le manuelAppel d'une méthode à l'intérieur d'une classe Ruby? (ou est-ce magique de rails)

Ceci est un code fragment du screencast je regarde

class MachinesController < ApplicationController 
    #... 
    before_filter :login_required, :only => [:report] 
    #...  
    def index 
     #etc... 
    end 

    def login_required 
     #etc... 
    end 
end 

Dans le contexte des rails, je comprends que before_filter est un rappel qui méthode feu login_required lorsque l'action report est appelée. Cependant, ce n'est pas clair pour moi ce que c'est dans le contexte de ruby. Dans d'autres langages, les classes contiennent généralement des méthodes, des propriétés, des variables de classe et des constantes définies dans les accolades. Cependant, cela ressemble à un appel de fonction à l'intérieur de la classe, et certaines expériences ont montré que vous pouvez mettre du code dans vos définitions de classe et le faire appeler lorsque le programme s'exécute. Est-ce correct? Si oui, existe-t-il des règles contextuelles spéciales pour le code qui est inséré dans une classe comme ça? (c'est-à-dire que la fonction before_filter dans les rails sait de quelle classe elle a été appelée) Sinon, quelle magie font les rails ici?

+0

OMI, vous devriez choisir la réponse de Sarah Mei comme votre «réponse choisie», elle fournit l'explication la meilleure et la plus complète. – horseyguy

+0

La réponse de Sarah est géniale, mais c'est une question que je n'ai pas posée. J'ai été confus par l'appel de méthodes à l'intérieur d'une classe, quelque chose que vous ne pouvez pas faire en PHP ou en Java. Je voulais savoir s'il y avait de la magie dans les rails, ou si Ruby le supportait, et si Ruby le supportait, quel était le code d'appel w/r/t différent dans une classe. Jonathan a répondu cela en expliquant comment l'identité a changé. –

+0

Peut-être que la question devrait être éditée un peu, je pensais quelque chose comme: "Ruby: Appeler une fonction dans une définition de classe" –

Répondre

5

before_filter n'est pas réellement un rappel. C'est un class method of ActiveRecord::Base qui configure un rappel lorsque vous l'appelez. Ainsi, dans cet exemple:

before_filter :login_required, :only => [:report] 

Lorsque la classe est chargée, la méthode est appelée, et il ajoute :login_required à la chaîne de filtre pour la méthode report.

La convention pour ces types d'appels est de laisser tomber parens, mais il fonctionne très bien (et serait plus facilement identifiable comme un appel de méthode) si vous avez fait ceci:

before_filter(:login_required, :only => [:report]) 
+0

+1 meilleure réponse pour l'instant – horseyguy

0

Ruby est tellement cool. Vous pouvez certainement envoyer des messages depuis un bloc de classe. Si je comprends bien, ce que les choses comme class font, autre que l'évidence, est de contrôler l'identité de self. Ainsi, vous devriez pouvoir appeler n'importe quelle méthode de la classe ou des modules inclus à partir de là.

+0

Ah, je n'avais pas encore rencontré le mot-clé self ou appris à définir des méthodes statiques. Cela a beaucoup plus de sens maintenant (mais est encore énormément bizarre) –

+1

Vous ne pouvez pas invoquer une méthode définie sur un 'module inclus' à partir d'une définition de classe. Afin d'invoquer une méthode fournie par un module dans la définition de la classe, le module doit être "étendu" et non "include'd" dans la classe. – horseyguy

0

Je ne sais pas exactement ce que votre question est, mais voici mon interprétation:

before_filter 

Ceci est un appel de méthode de classe voir ActionController

:login_required 

Ceci est un paramètre à la méthode before_filter , et utilisé comme rappel à l'aide Object#send

:only => [:report] 

Th est un paramètre Hash supplémentaire à before_filter voir à nouveau ActionController.

Je suggèrerais également de regarder l'implémentation de la méthode before_filter pour l'insight.

+0

Ma question/confusion est centrée sur le fait que vous exécutez du code autre que des affectations ou des définitions de méthodes à partir d'un bloc de classe. Vous ne pouvez pas le faire dans des langages comme Java ou PHP et je cherche une explication/tutoriel sur la façon dont le code qui s'exécute avec une classe (pas une méthode de classe) diffère du code qui s'exécute en dehors d'une définition de classe. –

+0

Ahhh, je vois maintenant. :) – hobodave

+0

Heh, je viens de réaliser que c'est quelque chose que j'ai toujours pris pour acquis et que je n'ai jamais remis en question. Maintenant, je suis curieux et essaie de trouver l'explication moi-même. Vous devriez mettre à jour votre question pour clarifier un peu ce dont vous avez besoin, votre commentaire était clair - la question n'est pas. – hobodave

1

Contrairement à d'autres Dans Ruby, la classe peut être modifiée à l'exécution et vous pouvez effectuer des appels de fonction à partir de la définition de la classe.Donc ce qui se passe dans ce cas est que vous appelez la fonction before_filter, qui modifie ensuite la définition de la classe MachinesController lors de l'exécution.

C'est le mécanisme qui permet d'obtenir une syntaxe d'une beauté saisissante (au moins pour mes yeux) avec Rails, où il semble presque que vous utilisiez une sorte de langage spécifique au domaine pour décrire vos modèles. Des choses comme les appels de fonction validates, has_many et belongs_to sur les classes de modèle. D'après ce que je comprends, on appelle cela une macro et elle relève de la programmation méta. Vous pouvez read more about this topic.

Questions connexes