Metody chronione i prywatne w Rails

Widoczność metod w Rubim (metody publiczne, chronione i prywatne) została dobrze wyjaśniona w miejscach takich jak Ten post na blogu . Ale w Ruby on Rails wydaje się nieco inny niż w zwykłej aplikacji Ruby ze względu na sposób, w jaki Framework jest skonfigurowany. Tak więc w modelach Rails, kontrolerach, helperach, testach itp., kiedy należy / nie należy stosować metod chronionych lub prywatnych?

Edit : Dzięki za odpowiedzi na razie. Rozumiem pojęcie ochrony i prywatne w Ruby, ale szukam bardziej wyjaśnienia typowego sposobu, w jaki te typy widoczności są używane w kontekście różnych elementów aplikacji Rails (modele, Kontrolery, helpery, testy). Na przykład metody public controller są metodami akcji, metody chronione w kontrolerze aplikacji są wykorzystywane do "metod pomocniczych", do których ma być dostęp kilka kontrolerów, itd.

Author: jrdioko, 2010-12-21

5 answers

Dla modeli, idea jest taka, ż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 taka sama praktyka jak w innych językach obiektowych.

Dla kontrolerów i testów, rób, co chcesz. zarówno klasy controller jak i testowe są tylko instancjonowane i wywoływane przez framework ( tak, Wiem, że możesz teoretycznie Pobierz kontroler z widoku, ale jeśli to zrobisz, i tak coś jest dziwne). Ponieważ nikt nigdy nie stworzy tych rzeczy bezpośrednio, nie ma przed czym "chronić".

Dodatek / korekta: w przypadku kontrolerów należy oznaczyć metody "helper" jako chronione prywatne, a tylko same akcje powinny być publiczne. Framework nigdy nie przekieruje żadnych przychodzących wywołań HTTP do akcji/metod, które nie są publiczne, więc metody pomocnicze powinny być chronione w ten sposób.

Dla helperów nie ma znaczenia, czy metoda jest chroniona czy prywatna, ponieważ zawsze nazywa się ją"bezpośrednio".

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

 98
Author: averell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-01 15:56:09

Używasz prywatnej metody, jeśli chcesz nikt inny, jak tylko self użyć metody. Używasz metody chronionej, jeśli chcesz, aby tylko self and is_a?(self) S mogły ją wywołać.

Dobrym zastosowaniem protected może być użycie "wirtualnej" metody inicjalizacji.

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

Update: Od kiedy to napisałem, niektóre rzeczy się zmieniły w Ruby 2.0+ Aaron Patterson ma doskonały zapis http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html

 62
Author: EnabrenTane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-06 23:30:29

Różnica między ochroną a prywatność jest subtelna. Jeśli metoda jest chroniony, może być wywoływany przez dowolne instancja klasy definiującej lub jej podklasy. Jeśli metoda jest prywatna, to może być wywołana tylko w kontekście obiektu wywołującego - - - nigdy nie jest możliwość dostępu do innego obiektu prywatne metody instancji bezpośrednio, nawet jeśli obiekt jest tego samego Klasa jako rozmówca. Do ochrony metody, są one dostępne z Obiekty tej samej klasy (lub dzieci).

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

 9
Author: nunopolonia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-20 23:54:15

Wydaje się, że masz dobre pojęcie o semantyce widzialności klas (public/protected/private) stosowanej w metodach. Wszystko, co mogę zaoferować, to szybki zarys sposobu, w jaki implementuję go w moich aplikacjach Rails.

Implementuję metody protected w kontrolerze aplikacji bazowej, 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óre chcę używać we wszystkich z nich w modelu bazowym, z którego wszystkie dziedziczą.

 3
Author: Sasha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-04 07:09:46

Chociaż akcje muszą być publicznymi metodami kontrolera, nie wszystkie metody publiczne muszą być akcjami. Możesz użyć hide_action Jeśli używasz trasy typu catch-all, takiej jak /:controller/:action/:id lub jeśli jest ona wyłączona (domyślnie w Rails 3), wtedy będą wywoływane tylko metody z jawnymi trasami.

Może to być przydatne, jeśli przekazujesz instancję kontrolera do innej biblioteki, takiej jak silnik szablonów Liquid, ponieważ możesz zapewnić publiczny interfejs zamiast używać send in your Liquid filtry i znaczniki.

 2
Author: pixeltrix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-29 21:16:39