Rails Way 处理多条路线上可用的操作

发布于 2024-10-27 04:02:17 字数 708 浏览 0 评论 0原文

我有以下路线:

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

我想知道是否有上述问题的标准解决方案,或者是否有更好的方法。

I have the following routes:

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 ]

Everything looks right, except 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

I was wondering if there's a standard solution to the problem above, or if there is a better way to do it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

扮仙女 2024-11-03 04:02:17

你所拥有的很好,但如果你愿意,你也可以使用两种不同的操作。这种方法应该允许您稍后更轻松地更改视图,并且更安全一些。

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'

What you have there is fine, but if you want you can use two different actions as well. This approach should allow you to more easily change the view later on, and is a bit safer.

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

It will also keep your controller code a little cleaner and less susceptible to odd queries like /products/10/reviews?user_id=100 which would result in the user's reviews being shown instead of the product's reviews.

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

The other alternative is to use different controllers as well:

match '/products/:product_id/reviews' => 'product_reviews#index'
match '/users/:user_id/reviews' => 'user_reviews#index'
少跟Wǒ拽 2024-11-03 04:02:17

有些插件有办法为你加载资源,例如 declarative_authorization 或 cancan,我确信还有其他插件。

我见过的其他解决方案是在控制器中创建一个私有方法来加载对象,并且该方法中的逻辑本质上与您此处的逻辑相同;它只是将其移出索引操作本身。该方法也可以称为前置过滤器。

另一种执行逻辑的方法是从父对象开始(如果您也需要父对象,那就太好了:

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

Some plugins have ways to load resources for you, such as declarative_authorization or cancan, I'm sure there are others.

Other solutions I have seen is to make a private method in the controller to load the object, and in that method is essentially the same logic you have here; it just moves it out of the index action itself. The metod can also then be called as a before filter.

One other way to do your logic is to start with the parent object (nice if you need the parent object too:

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
浅黛梨妆こ 2024-11-03 04:02:17
def index
  key = [:user_id, :product_id].find{|k| params[k]}
  @reviews = Review.where(key => params[key]).first
  respond_with @reviews
end
def index
  key = [:user_id, :product_id].find{|k| params[k]}
  @reviews = Review.where(key => params[key]).first
  respond_with @reviews
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文