2011-03-25 3 views
5

I가 다음과 같은 경로 :레일 웨이는 여러 경로에서 가능한 조치를 처리하는

resources :users do 
    # List reviews made by user 
    resources :reviews, :only => [ :index ] 
end 

resources :products do 
    # List reviews by product, and provide :product_id for creation 
    resources :reviews, :only => [ :index, :new, :create ] 
end 

# Other actions don't depend on other resources 
resources :reviews, :except => [ :index, :new, :create ] 

모든 것이 ReviewsController#index 제외하고, 바로 같습니다

def index 
    if params[:user_id] 
    @reviews = Review.find_all_by_user_id params[:user_id] 
    else 
    @reviews = Review.find_all_by_product_id params[:product_id] 
    end 
    respond_with @reviews 
end 

받는 표준 솔루션이 있는지 궁금 해서요 위의 문제 또는 더 나은 방법이있는 경우.

답변

6

당신이 가지고있는 것은 괜찮습니다.하지만 원할 경우 두 가지 다른 행동을 사용할 수도 있습니다. 이 방법을 사용하면 나중에보기를보다 쉽게 ​​변경할 수 있으며 조금 더 안전합니다.

match '/products/:product_id/reviews' => 'reviews#product_index' 
match '/users/:user_id/reviews' => 'reviews#user_index' 

대신 제품의 리뷰로 표시되고 또한 컨트롤러 코드를 조금 청소기를 유지하고 사용자의 리뷰를 초래 /products/10/reviews?user_id=100 같은 이상한 쿼리에 덜 민감합니다.

def product_index 
    @reviews = Review.find_all_by_product_id params[:product_id] 
    respond_with @reviews 
end 

def user_index 
    @reviews = Review.find_all_by_user_id params[:user_id] 
    respond_with @reviews 
end 

다른 대안은뿐만 아니라 다른 컨트롤러를 사용하는 것입니다

match '/products/:product_id/reviews' => 'product_reviews#index' 
match '/users/:user_id/reviews' => 'user_reviews#index' 
+1

아주 좋은 제안. 나는'RESTful actions' 정신을 벗어 버려야한다고 생각합니다. :) –

+1

가끔은 효과가 있으며 때로는 방해가되는 경우도 있습니다. 완전히 평온한 행동을 고수하고 싶다면 컨트롤러를 덮어 쓰는 것보다 컨트롤러를 덮어 쓸 수 있으므로 편안한 ProductReviewsController와 편안한 UserReviewsController를 가질 수 있습니다. 물론 많은 예외 및 유일한 문을 이미 사용하고 있으므로 명시 적 URL 일치를 사용하면 내 예제와 같이 가장 적합한 솔루션이 될 수 있습니다. –

+1

나는 어떤 사람들이 너무 쉬었다는 말을 들었습니다. 나는 때때로 여러분이 탈출 할 필요가 있다는 데 동의합니다. 그러나 이것은 그렇게 보이지 않습니다. 사실, 두 개의 컨트롤러를 만들어 두 가지 리소스 (인덱스 동작 만)의 나머지 스타일을 깨고 있습니다. 이 경우, 나는 그것을 하나의 컨트롤러에 유지하고 params에 적절하게로드 할 것입니다. – DGM

0
def index 
    key = [:user_id, :product_id].find{|k| params[k]} 
    @reviews = Review.where(key => params[key]).first 
    respond_with @reviews 
end 
+0

왜'.first' 그것은 당신에게 하나 개의 리뷰를주지이를 – Galen

1

일부 플러그인은 declarative_authorization 또는 캉캉으로 당신을 위해 자원을로드하는 방법을 가지고, 내가 다른 사람이 확신 해요.

내가 본 다른 솔루션은 컨트롤러에서 개체를로드하는 개인 메서드를 만드는 것이며 그 메서드에서 본질적으로 여기있는 논리입니다. 인덱스 동작 자체에서 이동합니다. 또한 metod는 before 필터로 호출 될 수 있습니다.

로직을 수행하는 또 다른 방법은 (부모 개체와 함께 시작하는 것입니다

좋은 당신도 부모 개체가 필요한 경우 :?.

 
before_filter :load_collection, :only => :index 

private 
def load_collection 
    if params[:user_id] 
    @user = @parent = User.find(params[:user_id]) 
    else 
    @product = @parent = Product.find(params[:product_id]) 
    end 
    @reviews = @parent.reviews 
end 
관련 문제