Защищенные и приватные методы в Rails - PullRequest
80 голосов
/ 21 декабря 2010

Видимость методов в Ruby (общедоступные, защищенные и закрытые методы) хорошо объясняется в таких местах, как это сообщение в блоге . Но в Ruby on Rails он выглядит немного иначе, чем в обычном Ruby-приложении, из-за способа настройки фреймворка. Итак, в моделях Rails, контроллерах, помощниках, тестах и ​​т. Д. Когда / не целесообразно использовать защищенные или закрытые методы?

Редактировать : Спасибо за ответы до сих пор. Я понимаю концепцию защищенного и закрытого доступа в Ruby, но я ищу больше объяснения того, как эти типы видимости используются в контексте различных частей приложения Rails (модели, контроллеры, помощники, тесты) , Например, общедоступные методы контроллера - это методы действий, защищенные методы в контроллере приложения используются для «вспомогательных методов», к которым должны обращаться несколько контроллеров и т. Д.

Ответы [ 5 ]

104 голосов
/ 05 января 2011

Для моделей идея состоит в том, что открытые методы являются открытым интерфейсом класса.Публичные методы предназначены для использования другими объектами, в то время как защищенные / частные методы должны быть скрыты извне.

Это та же практика, что и в других объектно-ориентированных языках.

Для контроллеры и тесты, просто делайте как хотите. И контроллер, и тестовые классы только создаются и вызываются платформой ( да, я знаю, что вы можете теоретически получить контроллер из представления, но если вы сделаете это, что-то странное в любом случае ).Поскольку никто никогда не создаст эти вещи напрямую, не от чего будет «защищаться».

Добавление / исправление: Для контроллеров вы должны пометить «вспомогательные» методы как protected частный, и только сами действия должны быть публичными.Фреймворк никогда не будет направлять входящие HTTP-вызовы на действия / методы, которые не являются общедоступными, поэтому ваши вспомогательные методы должны быть защищены таким образом.

Для помощников не имеет значения, является ли метод защищенным или закрытым,так как они всегда называются «напрямую».

Вы можете пометить вещи защищенными во всех этих случаях, если это, конечно, облегчит вам понимание.

64 голосов
/ 21 декабря 2010

Вы используете приватный метод, если хотите, чтобы никто, кроме self, использовал метод. Вы используете защищенный метод, если хотите что-то, что может вызвать только self and is_a?(self) s.

Хорошее использование защищенного может быть, если у вас есть «виртуальный» метод инициализации.

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

Обновление: С тех пор, как я написал это, некоторые вещи изменились в Ruby 2.0+. Аарон Паттерсон отлично написал http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html

10 голосов
/ 21 декабря 2010

Разница между защищенным и частным невелика.Если метод защищен, он может быть вызван любым экземпляром определяющего класса или его подклассов.Если метод является закрытым, он может быть вызван только в контексте вызывающего объекта - невозможно получить прямой доступ к закрытым методам другого экземпляра объекта, даже если объект того же класса, что и вызывающий объект.Для защищенных методов они доступны из объектов того же класса (или потомков).

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

3 голосов
/ 04 января 2011

Похоже, у вас есть хорошее представление о семантике видимости класса (публичной / защищенной / приватной) применительно к методам. Все, что я могу предложить, - это краткое описание того, как я реализую это в своих приложениях на Rails.

Я реализую защищенные методы в базовом контроллере приложения, чтобы они могли вызываться любым контроллером через фильтры (например, before_filter: method_foo). Аналогичным образом я определяю защищенные методы для моделей, которые я хочу использовать во всех них в базовой модели, от которой все они наследуются.

2 голосов
/ 07 января 2011

Хотя действия должны быть открытыми методами контроллера, не все открытые методы обязательно являются действиями. Вы можете использовать hide_action, если вы используете универсальный маршрут типа /:controller/:action/:id или если он отключен (по умолчанию в Rails 3), тогда будут вызываться только методы с явными маршрутами.

Это может быть полезно, если вы передаете экземпляр контроллера какой-либо другой библиотеке, такой как шаблонизатор Liquid, поскольку вы можете предоставить общедоступный интерфейс вместо необходимости использовать send в ваших фильтрах и тегах Liquid.

...