Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails routes with scope ":locale" and shallow nested resources

So I want to have Rails handle locale-specific routes for me, e.g.

/en/companies
/nl/companies

That works great with the routes definition:

scope "(:locale)", :locale => /en|nl/ do
  resources :companies
end

But at the same time companies have shallow nested resources, like so:

scope "(:locale)", :locale => /en|nl/ do
  resources :companies, :shallow => true do
    resources :pages
  end
end

That allows paths like /en/companies/1/pages, but not paths like /en/pages/1/edit. Since "shallow" also strips the "locale" part of the path, it seems I'm stuck with /pages/1/edit?locale=en. Is there no way to get Rails to handle shallow nested resources with locales in such a way that I can use /en/pages/1/edit?

like image 485
Pascal Lindelauf Avatar asked Jun 21 '11 08:06

Pascal Lindelauf


2 Answers

Ah, yes! I found the answer in the API documentation. The magic is in the :shallow_path keyword and in the above example it works like so:

scope :path => "(:locale)", :shallow_path => "(:locale)", :locale => /en|nl/ do
  resources :companies, :shallow => true do
    resources :pages
  end
end

Now an URL like /en/pages/1/edit works perfectly!

like image 173
Pascal Lindelauf Avatar answered Sep 22 '22 12:09

Pascal Lindelauf


Thanks a lot Pascal, this was really useful to me. I noticed a similar behavior when setting up my nested resources.

I would add something, the option of using a block statement for shallow instead of a parameter. Right now using the syntax you gave, only the direct descendants (:pages) will be shallow.

If by any chance you want to nest one level deeper (let's skip the argument about whether this is best practices or not), using a shallow block will carry the shallowness as deep as necessary:

resources :users do 
  shallow do
    resources :categories do
      resources :sections do
        resources :pages
      end
    end
    resources :news
  end
end

Here's an example of what available routes helpers you will have for all of the resources nested within :users

new_category_section  GET    (/:locale)(/:locale)/categorys/:category_id/sections/new(.:format)     {:locale=>/fr|en/, :action=>"new", :controller=>"sections"}
edit_section          GET    (/:locale)(/:locale)/sections/:id/edit(.:format)                       {:locale=>/fr|en/, :action=>"edit", :controller=>"sections"}
section               GET    (/:locale)(/:locale)/sections/:id(.:format)                            {:locale=>/fr|en/, :action=>"show", :controller=>"sections"}
                      PUT    (/:locale)(/:locale)/sections/:id(.:format)                            {:locale=>/fr|en/, :action=>"update", :controller=>"sections"}
                      DELETE (/:locale)(/:locale)/sections/:id(.:format)                            {:locale=>/fr|en/, :action=>"destroy", :controller=>"sections"}

   section_pages      GET    (/:locale)(/:locale)/sections/:section_id/pages(.:format)              {:locale=>/fr|en/, :action=>"index", :controller=>"pages"}
                      POST   (/:locale)(/:locale)/sections/:section_id/pages(.:format)              {:locale=>/fr|en/, :action=>"create", :controller=>"pages"}
new_section_info_page GET    (/:locale)(/:locale)/sections/:section_id/pages/new(.:format)          {:locale=>/fr|en/, :action=>"new", :controller=>"pages"}
        dit_info_page GET    (/:locale)(/:locale)/pages/:id/edit(.:format)                          {:locale=>/fr|en/, :action=>"edit", :controller=>"pages"}
            info_page GET    (/:locale)(/:locale)/pages/:id(.:format)                               {:locale=>/fr|en/, :action=>"show", :controller=>"pages"}
                      PUT    (/:locale)(/:locale)/pages/:id(.:format)                               {:locale=>/fr|en/, :action=>"update", :controller=>"pages"}
                      DELETE (/:locale)(/:locale)/pages/:id(.:format)                               {:locale=>/fr|en/, :action=>"destroy", :controller=>"pages"}
like image 32
Olivier Lacan Avatar answered Sep 22 '22 12:09

Olivier Lacan