Is there a succinct way to define custom routes within a resource? - ruby-on-rails

Here's some code I have:
resources :things
post "/foo/bar" => "things#create"
Is there a more succinct/maintainable way to define the custom post route inside a block given to resources?

To answer the title question, use this in your routes file:
resources :things do
post 'foo/bar', on: :member, to: 'things#create'
end
If you want to create all the things routes under the foo path instead of things, use a path parameter to the resources call:
resources :things, path: 'foo'

Related

Missing :action key on routes definition Rails

I am getting the following error:
Missing :action key on routes definition, please check your routes.
For this route
resources :groups do
post '/groups/:id/add', on: :member
end
I have looked at several other SO answers on this but am not able to find one that helps me. What action is it missing?
This is not the right way to define routes. Actually router's member/collection accepts a key-value pair to generate the route. As you are defining a member function it will be like:
resources :groups do
member do
post :add
end
end
It will generate a route like: groups/1/add
If you use collection then it will generate: /groups/add
resources :groups do
collection do
post :add
end
end
Hope you get the idea.
Or
You can define specific route for this particular action like below:
match "/groups/:id/add" => "groups#add", via: :post
Key action here means controller action. as in
resources :groups do
post '/groups/:id/add', on: :member, action: "add"
end
Rails can't infer the action from a path. But you can define the action instead and rails will automatically figure out the path:
resources :groups do
post :add, on: :member
end

Rails how to make example.com/post/1 to example.com/blog/post/1

I have a blog with root
root 'posts#index'
And works best with example.com/ to example.com/posts
But what I want is something like this:
example.com/blog/posts/1.
I've tried creating blog Controller and add
resources :blog do
resources :posts
end
But this is making my routes to blog/:id/posts/:id
If you don't have the relationship between the post and the blog as you mentioned, rails gives you the freedom to declare routes as our own.
so, to make the route example.com/posts/1 to, example.com/blog/posts/1, just add a custom route at the last.
get '/blog/posts/:id', to: :show, controller: 'posts'
what this does is over rides the previous route and make this route final.
Now type rake routes and it will give the last route for you as,
GET /blog/posts/:id(.:format) posts#show
Now you can access using,
example.com/blog/posts/1
Reference for rails routing
Just to expand upon #Sravan answer. If you have multiple routes that will start with /blog/ you might want to check Rails guide on routing.
You can add something along the lines of
scope '/blog' do
resources :posts
resources :users
resources :images
end
Which will create corresponding routes under /blog/.
namespace :blog do
resources :posts
resources :users
resources :images
end
And your controller with namespace will look like this: Blog::PostsController

named route not generating appropriate url helper

My named route is not generating the appropriate url helper for the following nested route:
resources :contacts do
match :promote_to_client, via: [:get,:post], on: :member, as: :promote_to_client
I am expecting a helper like promote_to_client_path. However, instead it is giving me promote_to_client_contact_path (which is the default). What might I be doing wrong?
Rails prefixes the helper names with whatever resource they are nested in:
resources :books do
resorces :chapters
end
Would give book_chapters_path etc. This can be customized through the shallow_prefix option:
resources :books, shallow_prefix: 'secret' do
resorces :chapters
end
secret_chapters_path

How to define a Rails route on resource member and have it appear at the end of the route name?

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.

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.

Resources