web-dev-qa-db-fra.com

Méthodes protégées et privées dans Rails

La visibilité des méthodes dans Ruby (méthodes publiques, protégées et privées) a été bien expliquée dans des endroits tels que cet article de blog . Mais dans Ruby sur Rails, il semble légèrement différent de ce qu'il serait dans une application normale Ruby en raison de la façon dont le cadre est configuré. Ainsi, dans Rails modèles, contrôleurs, aides, tests, etc., quand est-il/ne convient-il pas d'utiliser des méthodes protégées ou privées?

Edit : Merci pour les réponses jusqu'à présent. Je comprends le concept de protected et private dans Ruby, mais je cherche plus à expliquer la manière typique dont ces types de visibilité sont utilisés dans le contexte des différentes pièces d’une application Rails (modèles, contrôleurs, aides, tests). Par exemple, les méthodes de contrôleur public sont des méthodes d'action. Les méthodes protégées dans le contrôleur d'application sont utilisées pour les "méthodes d'assistance" auxquelles plusieurs contrôleurs doivent accéder, etc.

80
jrdioko

Pour les modèles, l'idée est que les méthodes publiques constituent l'interface publique de la classe. Les méthodes publiques sont destinées à être utilisées par d'autres objets, tandis que les méthodes protégées/privées doivent être masquées de l'extérieur.

C'est la même pratique que dans d'autres langages orientés objet.

Pour contrôleurs et des tests, faites comme bon vous semble. Contrôleur et les classes de test sont seulement instanciées et appelées par le framework (oui, je sais que vous pouvez théoriquement obtenir le contrôleur de la vue, mais si vous faites cela, quelque chose d'étrange quand même). Puisque personne ne créera jamais ces choses directement, il n'y a rien contre quoi "protéger".

Addendum/Correction: Pour les contrôleurs, vous devez marquer les méthodes "helper" comme protégé privé, et seules les actions elles-mêmes doivent être publiques. La structure ne routera jamais les appels HTTP entrants vers des actions/méthodes qui ne sont pas publiques. Par conséquent, vos méthodes d'assistance doivent être protégées de cette manière.

Pour les assistants, le fait qu'une méthode soit protégée ou privée ne fera aucune différence, car ils sont toujours appelés "directement".

Vous pouvez marquer les éléments comme protégés dans tous ces cas si cela vous facilite la compréhension, bien sûr.

104
averell

Vous utilisez une méthode privée si vous ne voulez personne d'autre que self utiliser une méthode. Vous utilisez une méthode protégée si vous voulez que quelque chose que self and is_a?(self) s puisse appeler.

Une bonne utilisation de protected pourrait être si vous aviez une méthode d'initialisation "virtuelle".

class Base
    def initialize()
        set_defaults()
        #other stuff
    end

    protected
    def set_defaults()
        # defaults for this type
        @foo = 7
        calculate_and_set_baz()
    end

    private
    def calculate_and_set_baz()
        @baz = "Something that only base classes have like a file handle or resource"
    end
end

class Derived < Base
    protected
    def set_defaults()
        @foo = 13
    end
end

@foo aura des valeurs différentes. et les instances dérivées n'auront pas @baz

Mise à jour: Depuis que j'ai écrit ceci, certaines choses ont changé dans Ruby 2.0+. Aaron Patterson a une excellente rédaction http://tenderlovemaking.com/2012/09/07/protected -methods-and-Ruby-2-0.html

65
EnabrenTane

La différence entre protégé et privé est subtile. Si une méthode est protégée, elle peut être appelée par n’importe quelle instance de la classe de définition ou de ses sous-classes. Si une méthode est privée, elle ne peut être appelée que dans le contexte de l'objet appelant. Il n'est jamais possible d'accéder directement aux méthodes privées d'une autre instance d'objet, même si l'objet appartient à la même classe que l'appelant. Pour les méthodes protégées, elles sont accessibles à partir d'objets de la même classe (ou des enfants).

http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Classes#Declaring_Visibility

10
nunopolonia

Vous semblez avoir une bonne idée de la sémantique de la visibilité des classes (public/protected/private) appliquée aux méthodes. Tout ce que je peux offrir est un bref aperçu de la façon dont je l’implémente dans mes Rails applications.

J'implémente des méthodes protégées dans le contrôleur d'application de base afin qu'elles puissent être appelées par n'importe quel contrôleur via des filtres (par exemple, before_filter: method_foo). De la même manière, je définis des méthodes protégées pour les modèles que je souhaite utiliser dans chacun d'eux dans un modèle de base dont ils héritent tous.

3
Sasha

Bien que les actions doivent être des méthodes publiques d'un contrôleur, toutes les méthodes publiques ne sont pas nécessairement des actions. Vous pouvez utiliser hide_action si vous utilisez un itinéraire fourre-tout comme /:controller/:action/:id ou s'il est désactivé (la valeur par défaut est Rails 3), seules les méthodes comportant des itinéraires explicites seront appelées.

Cela peut être utile si vous transmettez l'instance de contrôleur à une autre bibliothèque, telle que le moteur de gabarit Liquid, car vous pouvez fournir une interface publique plutôt que de devoir utiliser l'envoi de vos filtres et balises Liquid.

2
pixeltrix