2013-05-11 3 views
0

내가 내 응용 프로그램 컨트롤러에이 문제를 포함 할 지금이 코드를레일 : 모듈을 포함 시키지만 모듈 이름은 유지합니까?

module Auth 

    def sign_in(user) 
    #some stuff 
    session[:user_id] = user.id 
    end 

end 

을 고려하십시오.

ApplicationController < ActionController::Base 
    include Auth 
end 

이렇게하면 모든 컨트롤러에서 sign_in 메서드를 사용할 수 있습니다. 지금, 그것은 분명이, 내가 지금 내 컨트롤러 레일은 인증의 클래스 메소드를 찾습니다 때문에 작동하지 않습니다 분명히

def sign_user_in 
    # Some stuff 
    Auth.sign_in(@user) 
end 

이 읽기, 이름을 유지하고자하는 컨트롤러 액션 아님을 만들려면 기준 치수. 그래서 문제는 ... 컨트롤러에 모듈을 포함하고 이름이나 네임 스페이스를 유지하면서도 컨트롤러와 동일한 범위에 액세스 할 수 있습니까? (이 경우에는 세션 변수).

def current_user(controller) 
    User.find(controller.session[:user_id]) 
end 

이 메서드를 호출 :

지금까지 내가 함께 온 가장 나쁜 방법은 모듈을 포함 중지하고와 ApplicationController에 대신이 같은 인증 방법을 호출 할 때 함께 응용 프로그램 컨트롤러 인스턴스를 전달하다 인수로 self을 사용하여 컨트롤러에서 작동합니다.

+1

에 한번 컨트롤러 인스턴스를 전달해야합니다 노출의 모든 위험과 단일 네임 스페이스 이점이 없습니다. –

+0

단일 네임 스페이스의 이점은 무엇입니까? 너 무슨 소리 야? 컨트롤러 인스턴스에서 작동하는 메서드 모음이 있지만 응용 프로그램 컨트롤러가 뚱뚱해지기를 원하지 않습니다. 또한 상수가 제공하는 메서드 컨텍스트를 좋아합니다. 나는 그것이 가독성을 향상시킨다라고 생각한다. 나는 대신 접두사를 사용하고'auth_method_name'을 할 수 있음을 알고 있지만 실제로는'Auth.method_name'이 더 좋아 보인다. JavaScript는 실행 컨텍스트 덕분에이 점을 제공하지만 Ruby는 어떻게 처리합니까? "단일 네임 스페이스"에 도움이되는 것이 있다면 PHP를 프로그래밍 할 것입니다. –

+0

TL; DR. 믹스 인 내부에서 '세션'에 액세스하고 싶다고 명시 적으로 말했지만 믹서에서만, 컨트롤러에서는 그렇지 않습니다. 노출의 위험성, 유익 없음. 관심사를 분리하려면 * 분리하고 서비스 객체를 사용하십시오. 간단히 기능을 믹스 인으로 옮기더라도 컨트롤러를 덜 뚱뚱하게 만들지는 않습니다. 격리 된 클래스로 이동 시키면됩니다. –

답변

1

시험해보십시오.

모든 기능에 실제 클래스를 사용하며 컨트롤러에는 해당 클래스의 인스턴스가 있습니다. 기본적으로 위가 동일한 코드 - current_user를 볼 수 있지만 당신은뿐만 아니라 두 세계의 최악의 것 모든 메소드 호출 IMO

module Auth 
    # this method is 'mixed' into controller (self) 
    def initialize_authorizer 
    @authorizer = ::Auth::Authorizer(self) 
    end 

    # this class doesn't need to be in this namespace (module), put it where ever makes sense 
    class Authorizer 
    def initialize(controller) 
     @controller = controller 
    end 

    attr_reader :controller 

    def sign_in(user) 
     #some stuff 
     controller.session[:user_id] = user.id 
    end 

    def current_user 
     User.find(controller.session[:user_id]) 
    end   
    end 
end 

ApplicationController < ActionController::Base 
    include Auth 

    before_filter :initialize_authorizer 
end 

def sign_user_in 
    # Some stuff 
    @authorizer.sign_in(@user) 
end  
+0

이것은 흥미로운 접근 방법입니다. 감사합니다. :-) –

+0

저는 인스턴스 변수를 사용하는 아이디어를 정말 좋아합니다. 귀하의 솔루션을 사용하면 네임 스페이스가 필요하지 않습니다. 컨트롤러 확장을 auth라는 클래스로 생성 한 다음 before_filter를 사용하여 응용 프로그램 컨트롤러에서 사용하도록 설정할 수 있습니다. –