Rails Rails 为何不允许 resources 中的 new, create 等 map 到自定义的 action?

mizuhashi · 2016年10月21日 · 最后由 Rei 回复于 2016年10月22日 · 2934 次阅读

场景是这样的,希望有如下实际路由

get '/order/:order_id/reviews/new' => 'reviews#new_review_for_order', as: :new_order_review
get '/product/:product_id/reviews/new' => 'reviews#new_review_for_product', as: :new_product_review

最初是想用嵌套资源实现,但是查了 resources 的 api 之后,发现没有办法把 new map 到别的 action,要使用的话只能用 match 自己写,为了具名路由可能还要放在底层。

由于我没有详细了解过 restful,想问问这种用法有意不允许的,还是只是 rails 没有提供相关功能呢?

resources :orders do
    resources :reviews, except: [:new] do
      collection do
        get 'new', to: 'review#new_review_for_order', as: :new
      end
    end
  end

生成路由如下: GET /orders/:order_id/reviews/new reviews#new_review_for_order new_order_reviews_path

参考链接:添加集合路由

最好不要这样用吧。。。

rails 的路由是可以随便定义的,不过不建议这么干,因为这样的话很容易乱套

#1 楼 @lixu19941116 这个是错误的,正确的具名路由是 new_order_review_path,我也不是很想打破 rails 的规则,不行的话我还是在 reviews 控制器按参数处理算了

其实 OrderReview 跟 ProductReview 不是一个东西。

#4 楼 @emanon 是一个东西,但是 view 层不同,一些 require login 之类的东西也不同

#5 楼 @mizuhashi 如果你参加了 rubyconf 2016 你肯定就不会再认为他们是同一个东西了

resource 和 model 是不应该划等号的 比如两个 model 间的关系就可以是一个单独的 resource 但我们很少把它做成一个单独的 model,毕竟 rails 设计上就是通过关联来约定 model 间关系的

一个标准的 controller 不应该包含 7 个标准动作以外的任何 public 方法

#5 楼 @mizuhashi Duck Typing 推论:如果长得不像鸭子,叫得不像鸭子,那么就不是鸭子。

#6 楼 @IChou #7 楼 @Rei

我之前的回复是对于 model 说的,你们说 controller 可以拆开两个我也同意,但是就算我想用 ProductReviewsController,你也得让我能把 new_product_review_path 匹配到 product_reviews#new 啊。。

我的理解是嵌套资源就对应着关联关系,但是路由这里不允许两种嵌套资源同时存在,那么也就是模型层的两种关联不能同时正确地表达了

#9 楼 @mizuhashi 我看不懂你想做什么,我说我会怎么做好了。

Controllers:

|- orders/reviews_controller.rb
|- products/reviews_controller.rb
|- orders_controller.rb
\- products_controller.rb

Routes:

resources :orders do
  resources :reviews, controller: 'orders/reviews'
end

resources :products do
  resources :reviews, controller: 'products/reviews'
end

其实我觉得你这样的情况 使用浅层嵌套会更合适

#10 楼 @Rei 有 controller 这个 option 吗,我在http://edgeapi.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-resources没看到

我回去试试吧

找到了,是 match 的 option,那就没问题了

#10 楼 我觉得这样的方案可能更好

resources :orders do
  resources :reviews, shallow: true
end

resources :products do
  resources :reviews, shallow: true
end

对应的文件是

|- reviews_controller.rb
|- orders_controller.rb
\- products_controller.rb

浅层嵌套是一个伟大的设计,很大程度避免了深层嵌套导致的路由复杂,又可以代码复用

#14 楼 @IChou 按楼主需求,View 和权限都不同,最好分开两个 Controller。

mizuhashi 关闭了讨论。 10月22日 23:49
需要 登录 后方可回复, 如果你还没有账号请 注册新账号