Pundit 네임스페이스 정책의 기존 구현 방식은 AdminController와 같은 베이스 컨트롤러에서 policy_scope 및 authorize 메서드를 수동으로 오버라이딩하여 네임스페이스 심볼을 추가하는 형태입니다.
기존 Pundit 네임스페이스 정책 구현 예시
ruby
class AdminController < ApplicationController
def policy_scope(scope)
super([:admin, scope])
end
def authorize(record, query = nil)
super([:admin, record], query)
end
end
-
이 방식은 각 네임스페이스 베이스 컨트롤러마다 동일한 코드를 반복해야 하는 단점이 있습니다.
-
이는 코드 중복을 증가시키고 유지보수를 번거롭게 만듭니다.
제안하는 개선된 접근 방식: NamespacedPolicy Concern
이러한 문제를 해결하기 위해, NamespacedPolicy라는 Ruby 모듈 Concern이 제안됩니다. 이 Concern은 Module.new와 define_method를 사용하여 동적으로 policy_scope와 authorize 메서드를 생성하며, 지정된 네임스페이스 심볼을 자동으로 처리합니다.
ruby
# app/controllers/concerns/namespaced_policy.rb
module NamespacedPolicy
def self.Policy(scope)
Module.new do
define_method :policy_scope do |scope_class|
super([scope, scope_class])
end
define_method :authorize do |record, query = nil|
super([scope, record], query)
end
private :policy_scope, :authorize
end
end
end
-
NamespacedPolicy::Policy(:namespace_symbol)형태로 호출하여 특정 네임스페이스에 대한 정책 로직을 포함하는 익명 모듈을 생성합니다. -
생성된 모듈은
policy_scope와authorize메서드를 오버라이딩하여super호출 시 지정된scope를 자동으로 프리픽스로 추가합니다.
개선된 컨트롤러 구조
이 Concern을 베이스 컨트롤러에 포함하면, 컨트롤러 코드는 다음과 같이 간결해집니다.
ruby
class AdminController < ApplicationController
include NamespacedPolicy::Policy(:admin)
-
AdminController는 이제 단 한 줄의include문으로 네임스페이스 정책 기능을 완벽하게 지원하며, 코드 중복이 효과적으로 제거됩니다. -
하위 컨트롤러에서는
policy_scope와authorize를 평소처럼 호출할 수 있어 개발자 경험이 향상됩니다.