一个 'Posts' 资源有两条不同的路线?

One 'Posts' resource with two different routes?

我想使用一个 'posts' 控制器获取两条(或更多条)不同路线的所有 restful 路线。我在一个多品牌网站上工作,我正在努力减少重复代码。

brand1/blog/:id
brand2/blog/:id

现在我有:

resources :posts, :path => "brand1/blog"
     get 'brand2/blog' => 'posts#brand2_index'

我可以使用 @post.brand 参数让这两个博客正确显示,但个别 post url 最终总是针对 brand1。

我对 rails 和一般编程还很陌生,所以我肯定会遗漏一些基本知识。

非常感谢任何帮助。谢谢!

尝试如下嵌套您的资源,然后 运行 rake routes 看看您得到了什么。

resources :posts do
    get 'brand1/blog', to: "posts#brand1_index"
    get 'brand2/blog', to: "posts#brand2_index"
end

贾斯汀

处理此问题的一种简洁方法是使用范围。您可以这样定义路线:

scope ':brand_name' do
  resources :posts, path: 'blog'
end

无需重复控制器操作。在您的控制器中,您将获得带有 params[:brand_name] 的品牌。生成的路由如下:

    posts GET        /:brand_name/blog(.:format)                     posts#index
          POST       /:brand_name/blog(.:format)                     posts#create
 new_post GET        /:brand_name/blog/new(.:format)                 posts#new
edit_post GET        /:brand_name/blog/:id/edit(.:format)            posts#edit
     post GET        /:brand_name/blog/:id(.:format)                 posts#show
          PATCH      /:brand_name/blog/:id(.:format)                 posts#update
          PUT        /:brand_name/blog/:id(.:format)                 posts#update
          DELETE     /:brand_name/blog/:id(.:format)                 posts#destroy
     page GET        /pages/*id                                      high_voltage/pages#show

这通常包含在 nested resources:

#config/routes.rb
resources :brands, path: "", only: [] do
   resources :posts, path: "blog", only: [:index, :show] #-> url.com/:brand_id/blog/:id
end

由于您没有使用 brands 作为资源,因此您需要使用 scope(不需要控制器):

#config/routes.rb
scope :brand do
   resources :posts, path: "blog", only: [:index, :show] #-> url.com/:brand/blog/:id
end

然后您将能够在您的参数中选择 :brand

#app/controllers/posts_controller.rb
class PostsController < ApplicationController
   def show
     @brand = Brand.find params[:brand]
     @post  = @brand.posts.find params[:id]
   end
end

--

如果您想确保只有有效的品牌被接受为路线,您需要使用自定义约束:

#config/routes.rb
scope :brand, constraints: BrandExists do
    resources :posts, path: "blog", only: [:index, :show] #-> url.com/:brand/blog/:id
end

#lib/brand_exists.rb
module BrandExists

    def initializer(router)
        @router = router
    end

    def self.matches?(request)
        Brand.exists? request.path.split("/").first
    end

end

Very good ref here.