[ruby-on-rails] Rails의 보호 및 비공개 메서드

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

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



답변

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

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

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

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

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

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


답변

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


답변

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

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


답변

메서드에 적용되는 클래스 가시성 (공개 / 보호 / 개인)의 의미를 잘 알고있는 것 같습니다. 제가 제공 할 수있는 것은 Rails 앱에서 구현하는 방법에 대한 간단한 개요뿐입니다.

필터를 통해 모든 컨트롤러에서 호출 될 수 있도록 기본 애플리케이션 컨트롤러에 보호 된 메서드를 구현합니다 (예 : before_filter : method_foo). 비슷한 방식으로, 모두 상속받는 기본 모델의 모든 모델에서 사용하려는 모델에 대해 보호 된 메서드를 정의합니다.


답변

액션은 컨트롤러의 공용 메서드 여야하지만 모든 공용 메서드가 반드시 액션 인 것은 아닙니다. 다음 hide_action과 같은 포괄 경로를 사용 /:controller/:action/:id중이거나 비활성화 된 경우 (Rails 3의 기본값) 사용할 수 있으며 명시 적 경로가있는 메서드 만 호출됩니다.

Liquid 필터 및 태그에서 send를 사용하는 대신 공개 인터페이스를 제공 할 수 있으므로 Liquid 템플릿 엔진과 같은 다른 라이브러리에 컨트롤러 인스턴스를 전달하는 경우 유용 할 수 있습니다.


답변