How to tweak nested route - ruby-on-rails-3

I have routes like this:
namespace :admin do
resources :users, :only => :index do
resources :skills, :only => :index
end
end
resources :skills
In this case I got:
admin_user_skills GET /admin/users/:user_id/skills(.:format)
{:action=>"index", :controller=>"admin/skills"}
How to change nested route in order to point to SkillsController instead of Admin::SkillsController? I'd like to have this:
admin_user_skills GET /admin/users/:user_id/skills(.:format)
{:action=>"index", :controller=>"skills"}
Interesting thing - if we have no Admin::SkillsController, it will use SkillsController automatically, but only in development.

Using namespace in routes implies to have special directory for "namespaced" controllers, admin in your case. But if you use scope instead you have what you need:
scope '/admin' do
resources :users, :only => :index do
resources :skills, :only => :index
end
end

Related

Custom route for user/admin logins

I have a platform built in Ruby on Rails that supports creation of websites with their own content, users etc. I want this route to show the sign in page for devise:
devise_scope :user do
get '/websites/:website_id/users/sign_in' => 'devise/sessions#new', :as => :website_session end
I get error:
No route matches {:action=>"show", :controller=>"websites", :locale=>:en, :id=>nil}
My resources are set up in the routes file as below. What should I change?
devise_for :users, :controllers => {:registrations => "devise/custom/registrations", :sessions => "devise/custom/sessions"}
resources :websites do
resources :users end

Rename a custom member route named helper in Rails 3

I have routes listed as follows
resources :jobs do
resources :invoices, :only => [:show] do
get 'submit_invoice', :on => :member
end
end
So the middle route creates a url like /jobs/:job_id/invoices/:id/submit_invoice which is exactly what I want. However rails assigns the name submit_invoice_job_invoice to the path which is ugly and horrible to type.
How can I make the name just submit_invoice so that I can have submit_invoice_path and submit_invoice_url?
The answer should be:
get "/jobs/:job_id/invoices/:id/submit_invoice" => "invoices#submit_invoice",
:as => "submit_invoice"
resources :jobs do
resources :invoices, :only => [:show] do
get 'submit_invoice', :on => :member, :as => 'submit_invoice'
end
end
Use :as => 'routename' and invoke it as routename_path.
:)

link_to different behavior from rails2 to rails3

In rails2, I was able to have code like this:
link_to(user.company.name, user.company)
which would map to:
/companies/id
but in rails 3, this same line of code throws a error stating:
undefined method `user_companies_path'
The obvious fix is to do something like:
link_to(user.company.name, company_path(user.company))
But I was wondering if anyone could explain the reason behind the change? The logic seemed a lot cleaner.
EDIT: Adding samples of my routes
In rails2, my routes looked like:
map.resources :users, :except => :edit, :member => { :details => :get }
map.resources :companies, :except => :edit, :member => { :details => :get }
In rails3, my routes are:
resources :users, :except => :edit do
member do
get :details
end
end
resources :companies, :except => :edit do
member do
get :details
end
end
The short answer is that the Rails 3 routing API bases your application on resources which is why these RESTful routes are being used, and also means that it does things like support constraints.
In Rails 2, you'd do:
resources :cars do
resource :models
member do
post :year
end
collection do
get :details
end
end
In Rails 3, you'd do:
map.resources :cars, :member => {:year => :post}, :collection => {:details => :get} do |cars|
cars.resource :model
end
You also have the :as key available which means you can then use named route helpers anywhere that url_for is available (i.e. controllers, mailers etc.)

Refactor: Having a nested resource where the parent fails

I have the following resources setup:
resources :sites do
resources :documents
# more nested here
end
resources :documents do
resources :notes, :except => [:show, :new, :edit]
end
I want the notes controller to have the document context. The problem is, the document controller itself depends on the site context. So the /document urls that are created from the above all throw a 500 error. I could adjust the controller code to handle this, but i wonder if there's a way to not create the /document urls, just: /document/#id/notes
For any one else that may have this problem You can restrict the routes you don't want by using :except just the way #agmcleod has for the :notes. So to restrict the document urls would either be:
resources :sites do
resources :documents, :except => [:index, :show, :new, :create, :edit, :update, :destroy]
# more nested here
end
or
resources :documents, :except => [:index, :show, :new, :create, :edit, :update, :destroy] do
resource :notes, :except => [:show, :new, :edit]
end
You can remove any of the actions as necessary.

Adding methods to REST rails

I want to add more methods to my rest.
Here is my routes.rb file:
resources :boards, :except => [:new, :create] do
get 'customize', :on => :member
get 'change_template', :on => :member
get 'all_walls', :on => :member
end
I am getting them in the following format:
change_template_board GET /boards/:id/change_template(.:format) {:action=>"change_template", :controller=>"boards"}
But I want them in this format:
/boards/:board_id/change_template/:id(.:format)
How can I do that?
I'm copying the first answer from this question. In your routes.rb, you can add a new route dooit to resource fifi by adding this to your routes.rb file:
resources :fifi do
member do
get :dooit
end
end
This will create the route dooit_fifi along with the standard fifi, fifi_index, new_fifi, and edit_fifi routes.
If you want to restrict the routes created, you can do something like this:
resources :fifi, only: [:show, :create, :destroy] do
member do
get :dooit
end
end
which will produce only the routes dooit_fifi, fifi, and fifi_index.