I would like to create a resourceful route on a resource member, but I can't seem to find the syntax to create the named route that I want.
namespace :admin
resources :foobars do
get :attribute, on: :member, as: :attribute
end
end
This will provide a route method called:
attribute_admin_foobar_path
I would like it to say:
admin_foobar_attribute_path
The only other way I can think of would be to reject the resources block and create a single route:
namespace :admin
resources :foobars
get 'foobars/:id/attribute', as: :foobar_attribute
end
However, I don't like this approach because it forces me to duplicate the routing structure of already existing routes...not very DRY.
Is there a way that I can create the route name that I want while still using the resources routing block?
If you do it like this:
namespace :admin do
resources :foobars do
get :attribute
end
end
You will get:
admin_foobar_attribute GET /admin/foobars/:foobar_id/attribute(.:format) admin/foobars#attribute
That is admin_foobar_attribute_path.
Related
In Rails 5 I've figured out how to
Overwrite the route parameter from id to something like name
Add another route for a resource
So that my routes.rb looks something like this
Rails.application.routes.draw do
resources :cats, param: :name
resources :cats do
get :preview, on: :member
end
end
I've noticed however that my additional preview route does not keep the overwritten named route parameter. Instead, when looking at the output from rake routes, I have something that looks like this.
GET /cats/:id/preview(.:format)
when what I was expecting, and trying to achieve, was a route that looks like
GET /cats/:name/preview(.:format)
How do I both add an additional route to a resource while overwriting the parameter?
You're duplicating your routes entries for cats, and you've provided the block for declaring the preview route on the entry missing the param name override. You need to provide the override and the block in the same route declaration.
Rails.application.routes.draw do
resources :cats, param: :name do
get :preview, on: :member
end
end
This gives you the route you want:
$ rake routes
Prefix Verb URI Pattern Controller#Action
preview_cat GET /cats/:name/preview(.:format) cats#preview
I am creating a custom route like:
namespace :admin do
root 'users#index'
resources :users do
get 'admin_login' => 'users#admin_login'
end
end
But when I see with rake routes:
admin_user_admin_login GET /admin/users/:user_id/admin_login(.:format) admin/users#admin_login
Why :user_id is added here?
I just want it without :user_id.
Because you are creating a custom route within the users resource. Rails is doing exactly what you are telling it to do. You would like to show the "admin_login" route for a specified user (that's what you're currently telling rails to do).
Move the:
get 'admin_login' => 'users#admin_login'
Line of code outside of the resources block and you'll be able to create your custom route.
You need to specify an on option to tell Rails that it works on a collection and not a member resource. According to the official Rails routing guide
You can leave out the :on option, this will create the same member
route except that the resource id value will be available in
params[:photo_id] instead of params[:id].
You can also remove the => 'users#admin_login' part as that is the default behavior.
So the solution to your problem is to add on: :collection or place it inside a block like
namespace :admin do
root 'users#index'
resources :users do
collection do
get 'admin_login'
end
end
end
I have a namspaced resource, but I'd like a specific nested resource to route to a non-namespaced controller, e.g.:
namespace :admin do
resources :posts do # /admin/posts => Admin::PostsController
resources :audits, only: [:index] # /admin/posts/1/audits => AuditsController
end
end
The guides state that:
If you need to use a different controller namespace inside a namespace
block you can specify an absolute controller path, e.g: get '/foo' =>
'/foo#index'.
but this results in "wrong constant name" because rails tries to convert admin//audits in to a constant.
I ended up just splitting it out completely and doing
get 'admin/users/:user_id/audits', to: 'audits#index'
Still don't really understand the quote from the guides, I assume it must be incorrect.
I have a route in my Rails application that looks like this:
resources :products
get :specs, on: :member
end
This results in the route helper: specs_product_path instead of product_specs_path. How can I define the route so that the "specs action" is added to the end of the helper method instead of the beginning?
You can always declare a sub-resource which follows this convention:
resources :products do
resources :specs, only: [ :index ]
end
This will require creating another controller, though, with an index action.
You should also be able to override the name with the as: option:
resources :products do
get :specs, on: :member, as: :product_specs
end
Generally it's a good idea to adhere to convention as every exception can lead to confusion or conflict down the road.
I defined the following custom Rails route in routes.rb:
resources :projects do
get 'members'
end
This results in the following route (output from rake routes):
project_members GET /projects/:project_id/members(.:format)
What I would like, though, is for the route to map to this instead (change :project_id to :id)
project_members GET /projects/:id/members(.:format)
How can I make that happen?
Is members a nested resource? If so define it as one, and understand that this is why you have :project_id in the route, because :id in a nested resource is used by the final child item - you can't have multiple nested resources all using the same variable to define their id.
resources :projects do
resources :members
end
Add in a third level of nesting and it becomes a bit clearer to explain:
resources :projects do
resources :members do
resources :colours
end
end
With this nesting you could visit app/projects/:project_id/members/:member_id/colours/:id which would be served by the colours controller, which knows that :id defines an instance of that controllers model, and any other named id's belong to other resources.
Otherwise I think you just need to define it as a member method:
resources :projects do
member do
get 'members'
end
end
This tells the route that the action members is a non-resource action belonging to an instance of project, which I think should sort you out, but be sure it's the right thing to do.
See section 2.10 of Rails Routing from the Outside In