Railsの保護されたプライベートメソッド


81

Rubyでのメソッドの可視性(パブリックメソッド、プロテクトメソッド、プライベートメソッド)は、このブログ投稿のような場所で詳しく説明されています。しかし、Ruby on Railsでは、フレームワークの設定方法が原因で、通常のRubyアプリケーションとは少し異なるように見えます。それで、Railsモデル、コントローラー、ヘルパー、テストなどでは、保護されたメソッドまたはプライベートメソッドを使用することが適切である/適切でないのはいつですか?

編集:これまでの回答をありがとう。Rubyでの保護とプライベートの概念は理解していますが、Railsアプリのさまざまな部分(モデル、コントローラー、ヘルパー、テスト)のコンテキスト内でこれらのタイプの可視性が使用される一般的な方法の説明をもっと探しています。 。たとえば、パブリックコントローラメソッドはアクションメソッドであり、アプリケーションコントローラの保護されたメソッドは、複数のコントローラからアクセスする必要がある「ヘルパーメソッド」などに使用されます。

回答:


106

モデルの場合、パブリックメソッドはクラスのパブリックインターフェイスであるという考え方です。パブリックメソッドは他のオブジェクトによって使用されることを目的としていますが、保護/プライベートメソッドは外部から隠されています。

これは、他のオブジェクト指向言語と同じ方法です。

コントローラとテストについては、好きなように行ってください。コントローラークラステストクラスはどちらも、フレームワークによってインスタンス化されて呼び出されるだけですはい、理論的にはビューからコントローラーを取得できることはわかっていますが、そうすると、とにかく何かがおかしいです。)。誰もそれらを直接作成することはないので、「保護」するものは何もありません。

補遺/訂正:コントローラーの場合、「ヘルパー」メソッドを保護されたプライベートとしてマークし、アクション自体のみをパブリックにする必要があります。フレームワークは、着信HTTP呼び出しを公開されていないアクション/メソッドにルーティングすることはないため、ヘルパーメソッドはそのように保護する必要があります。

ヘルパーの場合、メソッドは常に「直接」呼び出されるため、メソッドが保護されているかプライベートであるかは関係ありません。

もちろん、理解しやすいものであれば、これらすべての場合に保護されているものにマークを付けることができます。


コントローラーの場合、「ヘルパー」メソッドを保護済みとしてマークし、アクション自体のみをパブリックにする必要があります。」コントローラーにプライベートメソッドを含めないようにアドバイスしていますか?それとも私はそれを文字通り読んではいけませんか?
デニス

2
最近はプライベートのみを使用しています。保護されたものとプライベートなものは、ほとんどの場所で同じ意味で使用されます。しかし、保護されていると、現実の世界では必要のない奇妙な動作が発生します。
averell 2014


66

メソッドを使用する以外に誰もself必要ない場合は、プライベートメソッドを使用します。何かだけが必要な場合は、保護されたメソッドを使用しますself and is_a?(self)sが呼び出すことができるます。

「仮想」初期化メソッドがある場合は、protectedを適切に使用できます。

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の値は異なります。派生インスタンスには@bazがありません

更新:私がこれを書いたので、Ruby2.0以降でいくつかの変更がありました。AaronPattersonは優れた記事を書いていますhttp://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html


9
あなたが言っself and is_a?(self)た方法が大好きです。私はいつも保護されたメソッドを子供たちのクラスで利用できると説明してきました。
テイトジョンソン

16
ここに注意!これは他の言語との重要な違いです。プライベートメソッドは子クラスで使用できます。privateメソッドとprotectedの唯一の違いは、「self.set_defaults」を使用して保護されたメソッドを呼び出すことができるのに対し、privateメソッドは「set_defaults」としてのみ呼び出すことができることです。
averell 2011年

良い答えですが、質問のポイントであるRailsという単語も含まれていません
Bryan Ash

5
彼の質問の編集タイムスタンプに注意してください。将来的には、質問が変更されたときに回答を更新するプライベートメソッドを定義します:)
EnabrenTane 2011年

アヴェレルが言ったように、この説明はルビーには当てはまりません。プライベートメソッドが子クラスにも表示される場合。
ミゲル

10

保護されたものとプライベートなものの違いは微妙です。メソッドが保護されている場合、それは定義クラスまたはそのサブクラスの任意のインスタンスによって呼び出される可能性があります。メソッドがプライベートの場合、呼び出し元オブジェクトのコンテキスト内でのみ呼び出すことができます---オブジェクトが呼び出し元と同じクラスであっても、別のオブジェクトインスタンスのプライベートメソッドに直接アクセスすることはできません。保護されたメソッドの場合、同じクラス(または子)のオブジェクトからアクセスできます。

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


2
リンクをありがとう。しかし、これらがRuby on Railsで具体的にどのように機能するかについてもっと疑問に思っています(パブリックコントローラーメソッドはアクションメソッドとして扱われ、アプリケーションコントローラーの保護されたメソッドは他のコントローラーで使用できます)
jrdioko 2010

3
最後のケースでは、「アプリケーションコントローラーの保護されたメソッドは他のコントローラーで使用できます」。これは、他のコントローラーが(通常)ApplicationControllerから継承するため、実際にはそれらのメソッドすべてを所有しているためです。彼らはapplication_controllerからそれらにアクセスしていません:これは決してインスタンス化されません。継承元の親として純粋に使用されます。
マックスウィリアムズ

3

メソッドに適用されるクラスの可視性(パブリック/保護/プライベート)のセマンティクスについては、よく理解しているようです。私が提供できるのは、Railsアプリに実装する方法の概要だけです。

保護されたメソッドをベースアプリケーションコントローラーに実装して、フィルターを介して任意のコントローラーから呼び出せるようにします(例:before_filter:method_foo)。同様の方法で、すべてのモデルが継承する基本モデルのすべてのモデルで使用する保護されたメソッドを定義します。


2

アクションはコントローラーのパブリックメソッドである必要がありますが、すべてのパブリックメソッドが必ずしもアクションであるとは限りません。のhide_actionようなキャッチオールルートを使用している場合、/:controller/:action/:idまたは無効になっている場合(Rails 3のデフォルト)に使用できます。明示的なルートを持つメソッドのみが呼び出されます。

これは、Liquidフィルターとタグでsendを使用するのではなく、パブリックインターフェイスを提供できるため、コントローラーインスタンスをLiquidテンプレートエンジンなどの他のライブラリに渡す場合に役立ちます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.