creating custom routes in rails - ruby-on-rails

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

Related

Customizing named route in Rails 3

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.

In RoR, do I have to specify every controller method as a route by hand?

What I'm wondering, in this case where I want to create a few web service type controllers, is if there is a way to "export" what method is allowed to be called from the controller. I'm still very new to RoR, and its routes feature, but in the end, is it expected that a fully functional RoR application just has hundreds of routes? Not every controller method I'm creating falls into a "resource" category.
Rails routes come in several varieties – RESTful routes are merely the ones that happen to provide native support for Rails resources. Remember that event resource routes can be modified to have member and collection routes:
# routes.rb
resources :products do
member do
get 'short' #=> products/:product_id/short/:id
post 'toggle' #=> products/:product_id/toggle/:id
end
collection do
get 'sold' #=> products/sold
end
end
You can also nest resource routes within other resource routes:
# routes.rb
resources :products do
resources :comments #=> RESTful routes patterned as products/:product_id/comments/:id/:action
resources :sales do
get 'recent', :on => :collection
end
end
Another handy feature is named routing. The following route is not resourceful:
# routes.rb
match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase # Creates route path akin to purchase_path(:id)
Namespaced routes can be very helpful for organization and readability:
# routes.rb
namespace :admin do
resources :products #=> RESTful routes patterned as admin/products/:product_id/:action
end
So, basically, there's a route for everything you want to do, whether it's RESTful/resourceful or not. But yes, you need to write a route for every action you want exposed to your app.
Using the routes.rb file, you can create routes or pattern matching for routes, as well as parameterized routes, and nested routes. You should read more about this here.
You can also give routes their own method name such as my_new_route_path. If you really wanted to, you could just hardcode routes into your HTML. Please don't do this.
Every controller action needs routes that map to it.

Rails routes to show action on custom route

I am trying to add a customer action to one of my resources, therefore I created a custom route:
namespace :admin do
resources :subscriptions
match 'subscriptions/summary', :to => 'subscriptions#summary', :as => 'subscriptions_summary'
end
In my rake routes I'm getting the following output:
admin_subscriptions_summary /admin/subscriptions/summary(.:format) spree/admin/subscriptions#summary
The problem now is, whenever I try to create a link to the summary action, I get following error:
Missing template spree/admin/subscriptions/show
Why is my app confusing the show action with the summary action?
namespace :admin do
resources :subscriptions do
collection do
get 'summary'
end
end
end
solved it.

Ruby on Rails : add a new route

I'm new with RoR so this is a newbie question:
if I have a controller users_controller.rb and I add a method foo, shouldn't it create this route?
http://www.localhost:3000/users/foo
because when I did that, I got this error:
Couldn't find User with id=foo
I of course added a view foo.html.erb
EDIT:
I added to routes.rb this code but I get the same error:
resources :users do
get "signup"
end
This doesn't work automatically in rails 3. You'll need to add
resource :users do
get "foo"
end
to your routes.rb
You'll definitely want to have a look at http://guides.rubyonrails.org/routing.html, it explains routing pretty well.
Rails is directing you to the show controller and thinks that you're providing foo as :id param to the show action.
You need to set a route that will be dispatched prior to being matched as /users/:id in users#show
You can accomplish this by modifying config/routes.rb by adding the following to replace your existing resource describing :users
resource :users do
get "foo"
end
Just to add to the other answers, in earlier versions of Rails there used to be a default route
match ':controller(/:action(/:id))(.:format)'
which gave the behaviour you describe where a request of the form controller/action would call the given method on the given controller. This line is still in routes.rb but is commented out by default. You can uncomment it to enable this behaviour but the comment above it explains why this is not recommended:
# This is a legacy wild controller route that's not recommended for RESTful applications.
# Note: This route will make all actions in every controller accessible via GET requests.
At the schema ':controller/:action(.:format)', you can also easily do the following
resources :users do
get "foo", on: :collection
end
or
resources :users do
collection do
get 'foo'
end
end
http://guides.rubyonrails.org/routing.html#adding-collection-routes

Custom actions in rails controller with restful actions?

I'm having some trouble with using creating my own actions inside a controller I generated using the scaffold.
I understand everything maps to the restful actions but I'm building a user controller where users can login/logout, etc but when I created the action and declared it in the routes.rb I get this error when I visit users/login
Couldn't find User with id=login
It tries to use login as a ID parameter instead of using it as an action.
Routes.rb
match 'users/login' => 'users#login'
I think I'm doing something wrong with the routes so if anybody could help me that would be great.
Thanks
I assume your routes.rb looks like this:
resources :users
match 'users/login' => 'users#login'
The problem is that Rails uses the first route that matches. From the documentation:
Rails routes are matched in the order they are specified, so if you have a resources :photos above a get 'photos/poll' the show action’s route for the resources line will be matched before the get line. To fix this, move the get line above the resources line so that it is matched first.
So either define your custom route before resources :users:
match 'users/login' => 'users#login'
resources :users
…or use this syntax for adding more RESTful actions:
resources :users do
collection do
match 'login'
end
end
To see the existing routes (and their order) run rake routes from the command line.

Resources