Pytanie Chronione i prywatne metody w Railsach


Widoczność metod w Ruby (publiczne, chronione i prywatne metody) została dobrze wyjaśniona w miejscach takich jak ten wpis na blogu. Ale w Ruby on Rails wygląda nieco inaczej niż w zwykłej aplikacji Ruby ze względu na sposób konfigurowania frameworka. Tak więc, w modelach Rails, kontrolerach, pomocnikach, testach itp., Kiedy jest / nie jest właściwe stosowanie metod chronionych lub prywatnych?

Edytować: Dzięki za odpowiedzi do tej pory. Rozumiem pojęcie chronionego i prywatnego w Ruby, ale szukam raczej wyjaśnienia, w jaki sposób te typy widoczności są używane w kontekście różnych elementów aplikacji Rails (modele, kontrolery, pomocnicy, testy) . Na przykład metody kontrolerów publicznych to metody działania, metody chronione w kontrolerze aplikacji są używane w "metodach pomocniczych", które muszą być dostępne dla wielu kontrolerów itp.


76
2017-12-20 23:45


pochodzenie




Odpowiedzi:


W przypadku modeli chodzi o to, że publiczne metody są publicznym interfejsem klasy. Metody publiczne są przeznaczone do użycia przez inne obiekty, podczas gdy metody chronione / prywatne mają być ukryte z zewnątrz.

Jest to ta sama praktyka, co w innych językach obiektowych.

Dla sterowniki i testy, po prostu rób, co chcesz. Zarówno kontroler, jak i klasy testowe są tworzone i wywoływane przez framework (tak, wiem, że teoretycznie możesz uzyskać kontroler z widoku, ale jeśli to zrobisz, to i tak coś jest dziwne). Ponieważ nikt nigdy nie stworzy tych rzeczy bezpośrednio, nie ma nic do "ochrony" przed.

Dodatek / korekta: W przypadku kontrolerów należy oznaczyć metody "pomocnika" jako chroniony prywatne, a same działania powinny być publiczne. Struktura nigdy nie będzie kierowała przychodzących wywołań HTTP do działań / metod, które nie są publiczne, więc twoje metody pomocnicze powinny być chronione w ten sposób.

Dla pomocników nie ma znaczenia, czy dana metoda jest chroniona, czy prywatna, ponieważ są one zawsze nazywane "bezpośrednio".

Możesz zaznaczyć rzeczy chronione we wszystkich tych przypadkach, jeśli oczywiście ułatwi to zrozumienie.


97
2018-01-05 17:47



"W przypadku kontrolerów należy oznaczać metody "pomocnicze" jako chronione, a same działania powinny być jawne."Czy radzisz nie mieć żadnych prywatnych metod w kontrolerach? A może nie powinienem czytać tego dosłownie? - Dennis
Obecnie używam tylko prywatnych. chronione i prywatne są używane zamiennie w większości miejsc; ale chronione przynosi dziwne zachowanie, którego nigdy nie potrzebowałem w prawdziwym świecie. - averell
Zwykle korzystam również z usług prywatnych. Jest to również zgodne z pewnymi wytycznymi, takimi jak Thoughtbot's "Użyj prywatnych zamiast chronionych przy definiowaniu metod kontrolera." - Dennis


Jeśli chcesz, użyj metody prywatnej nikt inny oprócz self używać metody. Używasz metody chronionej, jeśli chcesz tylko coś self and is_a?(self) s może zadzwonić.

Dobrym wykorzystaniem chronionych może być, jeśli masz "wirtualną" metodę inicjowania.

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 będzie mieć różne wartości. a instancje pochodne nie będą miały @baz

Aktualizacja: Odkąd to napisałem, niektóre rzeczy zmieniły się w Ruby 2.0+ Aaron Patterson ma świetny spis http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html


60
2017-12-21 00:08



Kochaj, jak powiedziałeś self and is_a?(self). Zawsze tłumaczyłem metody chronione jako dostępne w klasach dla dzieci. - Tate Johnson
Uwaga tutaj! Jest to istotna różnica w stosunku do innych języków: prywatne metody są również dostępne w klasach dla dzieci. Jedyną różnicą w zabezpieczeniach prywatnych i chronionych jest to, że można wywoływać metody chronione za pomocą "self.set_defaults", a metody prywatne można nazwać tylko "set_defaults". - averell
Odpowiednia odpowiedź, ale nie zawiera nawet słowa Rails, które jest punktem pytania - Bryan Ash
Zwróć uwagę na znacznik czasu edycji swojego pytania. W przyszłości określę prywatną metodę aktualizowania odpowiedzi, gdy będą zmieniać swoje pytania :) - EnabrenTane
Jak już powiedziałem, to wyjaśnienie nie dotyczy rubinu. Gdzie prywatne metody są również widoczne w klasach dla dzieci. - Miguel


Różnica między chronionym i   prywatny jest subtelny. Jeśli metoda jest   chronione, może być wywołane przez każdego   wystąpienie klasy definiującej lub jej   podklasy. Jeśli metoda jest prywatna, to jest   można wywoływać tylko w kontekście   obiektu wywołującego - nigdy nie jest   możliwy dostęp do innego obiektu   prywatne metody instancji bezpośrednio,   nawet jeśli obiekt jest taki sam   klasa jako dzwoniący. Dla chronionych   metody, są one dostępne z   obiekty tej samej klasy (lub   dzieci).

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


9
2017-12-20 23:54



Dzięki za link. Ale zastanawiam się więcej o tym, jak działają one w Ruby on Rails (metody kontrolerów publicznych są traktowane jako metody działania, metody chronione w kontrolerze aplikacji mogą być używane przez inne kontrolery itp.) - jrdioko
W ostatnim przypadku "metody chronione w kontrolerze aplikacji mogą być używane przez inne kontrolery", ponieważ inne kontrolery (ogólnie) dziedzicz z ApplicationController, więc oni sami są właścicielami wszystkich tych metod. Nie uzyskują dostępu do nich z poziomu application_controller: to nigdy nie jest tworzone. Jest używany wyłącznie jako rodzic do dziedziczenia. - Max Williams


Wydaje się, że masz dobry pomysł na semantykę widoczności klas (public / protected / private) stosowaną do metod. Wszystko, co mogę zaoferować, to szybki zarys sposobu, w jaki implementuję go w moich aplikacjach Railsowych.

Zaimplementowałem metody chronione w podstawowym kontrolerze aplikacji, aby mogły być wywoływane przez dowolny kontroler za pomocą filtrów (np. Before_filter: method_foo). W podobny sposób definiuję metody chronione dla modeli, których chcę używać we wszystkich modelach bazowych, z których wszystkie dziedziczą.


3
2018-01-04 07:09





Chociaż działania muszą być publicznymi metodami kontrolera, nie wszystkie publiczne metody to działania. Możesz użyć hide_action jeśli używasz trasy typu catch-all, np /:controller/:action/:id lub jeśli jest wyłączone (domyślnie w Railsach 3), wówczas zostaną wywołane tylko metody z jawnie wybranymi trasami.

Może to być przydatne, jeśli przekazujesz instancję kontrolera do innej biblioteki, takiej jak silnik szablonu Liquid, ponieważ możesz podać interfejs publiczny, zamiast korzystać z funkcji wysyłania w filtrach i znacznikach Liquid.


2
2018-01-07 11:36