Rails의 보호 및 비공개 메서드


81

Ruby의 메소드 가시성 (공개, 보호 및 비공개 메소드) 은이 블로그 게시물 과 같은 곳에서 잘 설명되어 있습니다 . 하지만 Ruby on Rails에서는 프레임 워크가 설정되는 방식 때문에 일반 Ruby 애플리케이션과 약간 다른 것처럼 보입니다. 그렇다면 Rails 모델, 컨트롤러, 헬퍼, 테스트 등에서 보호 또는 비공개 메서드를 사용하는 것이 적절하지 않은가?

편집 : 지금까지 답변 해 주셔서 감사합니다. Ruby에서 protected 및 private의 개념을 이해하지만 이러한 유형의 가시성이 Rails 앱의 다양한 부분 (모델, 컨트롤러, 도우미, 테스트)에서 사용되는 일반적인 방법에 대한 설명을 더 찾고 있습니다. . 예를 들어, 공용 컨트롤러 메서드는 작업 메서드이고, 애플리케이션 컨트롤러의 보호 된 메서드는 여러 컨트롤러에서 액세스해야하는 "도우미 메서드"등에 사용됩니다.

답변:


106

모델의 경우 공용 메서드가 클래스의 공용 인터페이스라는 아이디어가 있습니다. 공용 메서드는 다른 개체에 의해 사용되는 반면 보호 / 개인 메서드는 외부에서 숨겨집니다.

이것은 다른 객체 지향 언어에서와 동일한 관행입니다.

들어 컨트롤러와 당신이 원하는대로 테스트, 단지 않습니다. 컨트롤러와 테스트 클래스는 모두 프레임 워크에 의해 인스턴스화되고 호출됩니다 ( 예, 이론적으로 뷰에서 컨트롤러를 가져올 수 있다는 것을 알고 있지만 그렇게하면 어쨌든 이상한 일이 생깁니다 ). 아무도 이러한 것들을 직접 만들지 않기 때문에 "보호"할 것이 없습니다.

부록 / 수정 : 컨트롤러의 경우 "도우미"메서드를 보호 된 개인 으로 표시 해야하며 작업 자체 만 공용이어야합니다. 프레임 워크는 들어오는 HTTP 호출을 공개되지 않은 작업 / 메소드로 라우팅하지 않으므로 도우미 메서드를 이러한 방식으로 보호해야합니다.

도우미의 경우 메서드가 항상 "직접"으로 호출되기 때문에 메서드가 보호되거나 비공개인지 여부에 차이가 없습니다.

물론 이해하기 쉽도록 모든 경우에 보호 된 항목을 표시 할 수 있습니다.


" 컨트롤러의 경우"도우미 "메서드를 보호 된 것으로 표시해야하며 작업 자체 만 공개해야합니다. "컨트롤러에 개인 메서드를 사용하지 말라고 조언하고 있습니까? 아니면 문자 그대로 읽어서는 안 되나요?
Dennis

2
요즘은 개인용으로 만 사용합니다. 보호 및 개인은 대부분의 장소에서 같은 의미로 사용됩니다. 그러나 protected는 실제 세계에서 필요하지 않은 이상한 행동을 가져옵니다.
averell

2
나는 개인용으로 만 사용하는 경향이 있습니다. 이것은 또한 Thoughtbot의 "컨트롤러 메서드를 정의 할 때 보호되는 대신 개인 사용"
Dennis

67

다른 사람이 아니라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가 없습니다.

업데이트 :이 글을 쓴 이후로 Ruby 2.0+에서 몇 가지 사항이 변경되었습니다. Aaron Patterson은 훌륭한 글을 작성했습니다. http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html


10
당신이 말한 방식을 사랑하십시오 self and is_a?(self). 나는 항상 보호 방법을 어린이 수업에서 사용할 수 있다고 설명했습니다.
Tate Johnson

16
여기에주의하십시오! 이것은 다른 언어와의 중요한 차이점입니다. Private 메서드는 자식 클래스 에서도 사용할 수 있습니다. private 및 protected의 유일한 차이점은 "self.set_defaults"를 사용하여 보호 된 메서드를 호출 할 수있는 반면 개인 메서드는 "set_defaults"로만 호출 할 수 있다는 것입니다.
averell 2011 년

미세 대답하지만, 심지어는 질문의 포인트가되는 단어 레일이 포함되어 있지 않습니다
브라이언 애쉬

5
질문의 편집 타임 스탬프를 확인합니다. 앞으로 나는 그들이 그들의 질문을 변경하면 :) 내 대답을 업데이트 개인 방법을 정의합니다
EnabrenTane

averell이 말했듯이이 설명은 루비에는 적용되지 않습니다. private 메서드도 자식 클래스에서 볼 수 있습니다.
Miguel

10

보호와 개인의 차이는 미묘합니다. 메서드가 보호되는 경우 정의 클래스 또는 하위 클래스의 모든 인스턴스에서 호출 할 수 있습니다. 메서드가 private이면 호출 개체의 컨텍스트 내에서만 호출 될 수 있습니다. 즉, 개체가 호출자와 동일한 클래스에 있더라도 다른 개체 인스턴스의 개인 메서드에 직접 액세스 할 수 없습니다. 보호 된 메서드의 경우 동일한 클래스 (또는 자식)의 개체에서 액세스 할 수 있습니다.

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


2
링크 주셔서 감사합니다. 하지만 이것이 Ruby on Rails에서 어떻게 작동하는지 더 궁금합니다 (공용 컨트롤러 메서드는 액션 메서드로 취급되고, 애플리케이션 컨트롤러의 보호 된 메서드는 다른 컨트롤러에서 사용할 수 있습니다 등)
jrdioko

3
마지막 경우에 "애플리케이션 컨트롤러의 보호 된 메서드를 다른 컨트롤러에서 사용할 수 있습니다."이것은 다른 컨트롤러가 (일반적으로) ApplicationController 에서 상속 하므로 실제로 모든 메서드 자체를 소유하기 때문입니다. 그들은 application_controller에서 액세스하지 않습니다. 이것은 인스턴스화되지 않습니다. 상속 할 부모로 순수하게 사용됩니다.
Max Williams

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.