need help on rails nesting routes - ruby-on-rails

I want to get a route like
GET /example/notifications/status, to: example/notification#status
POST /example/notifications/disable to: example/notification#disable
Here is what I did
resources :example, only => %i[index] do
collection do
resources :notifications, :only => [] do
collection do
get :status
post :disable
end
end
end
end
it get the right path but it point to notification#status not example/notification#status
is there any way I can get both right path and controller expect code like
get "notifications/status", :to => "example/notifications#status"

You can use namespace for this purpose like below,
in you config/routes.rb file
namespace :example do
collection do
get :status
post :disable
end
end
It will hit the example/notification#status action.
for more information see here

Don't use resources since you don't want (aparently) any param on your routes. Go for namespace instead:
namespace :example do
namespace :notifications do
get 'status'
post 'disable'
end
end
Gives you:
$ rails routes -g example
Prefix Verb URI Pattern Controller#Action
example_notifications_status GET /example/notifications/status(.:format) example/notifications#status
example_notifications_disable POST /example/notifications/disable(.:format) example/notifications#disable

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

Add link to namespace'd route in Rails

Let's start off with some code:
Rails.application.routes.draw do
namespace :mpd do
get 'help' #==> get "mpd/help", as: :mpd_help
get 'status'
post 'start'
post 'stop'
post 'next'
post 'previous'
post 'pause'
post 'update'
# post 'play_song/:id', to: 'mpd#play_song'
end
# For some reason this path must not be in the namespace?!
post '/mpd/play_song/:id', to: 'mpd#play_song', as: 'mpd_play_song'
root 'static#home'
#match '*path' => 'static#home', via: [:get, :post]
end
Why do I have to specify the mpd_play_song_path outside of my namespace?
It uses the same controller and a function within, however, I receive the following error upon putting it within the namespace:
undefined method `mpd_play_song_path' for #<#<Class:0x007f2b30f7fd20>:0x007f2b30f7eb50>
And this is the line within my view:
= link_to("Play", mpd_play_song_path(song[:id])
I find this fairly strange and do not see any reason besides the passed id why it shouldn't work.
Hit me up if you need more code.
Thanks in advance,
Phil
Namespace
Having a namespace does not denote the controller your routes will assume.
A namespace is basically a folder within which you'll place controllers.
You still have to use the resources directive and set the controller actions:
#config/routes.rb
namespace :mdp do
resources :controller do
collection do
get :help #-> url.com/mdp/controller/help
end
end
end
It seems to me that you're wanting to use the mdp controller, which means you'd set up your routes as follows:
#config/routes.rb
resources :mdp do
get :help, action: :show, type: :help
get :status, action: :show, type: :status
...
end
A more succinct way will be to use constraints:
#config/routes.rb
resources :mdp, except: :show do
get :id, to: :show, constraints: ActionsConstraints
end
#lib/actions_constraints.rb
class NewUserConstraint
def self.matches?(request)
actions = %i(help status)
actions.include? request.query_parameters['id']
end
end

How to force to pass a required url path via get method

I have a route
collection do
get :show_logs
end
And I want the user should request show_logs/[:id].
Forbid user to send show_logs request without required id
What's the better ways to get it ?
UPDATE
If now, I wrote my rule as following,
And trying to access without :id, http://localhost:3000/tool/mvaas/relay_queries/show_logs
I'll get the error ActiveRecord::RecordNotFound in xxx
routes
get '/tool/mvaas/relay_queries/show_logs/:id', to: 'tool/mvaas/relay_queries#show_logs', :via => :get, :as => 'show_logs_tool_mvaas_relay_queries'
namespace :tool do
namespace :mvaas do
resources :relay_queries do
collection do
end
end
end
end
You should put it into member instead of collection
resources :users do
member do
get :show_logs
end
end
It will be accessible with the url /users/:id/show_logs
If you absolutely want the url to be /users/show_logs/:id then you should go with
get '/users/show_logs/:id', to: 'users#show_logs'
before your resources :users do block
You can verify if params exist by following way:
if(params.has_key?(:one))
If exist- request will done.
If absent - redirect/render or show notice.
you could try:
get "show_logs/:id" => "controller#action"
with updates: just write something like:
namespace :tool do
namespace :mvaas do
resources :relay_queries do
collection do
get "show_logs/:id", action: "show_logs"
end
end
end
end

routing is too verbose - rails

Suppose I have a model User and I want to add some dashboard namespace. So I create dashbord directory and put inside private_users_controller.rb. Now for routing I put
namespace "dashboard" do
resources :users do
member do
get "show" => "private_users#show"
end
end
end
the problem is that I only want to route the get request having this route /dashboard/users/:id/show. But rake routes shows a bunch of post, delete... routes.
How can I cut those ?
seems like you don't need any of the method from resources definition, so just add a match will be ok.
namespace "dashboard" do
match 'users/:id/show', :to => 'private_users#show'
end
if you insist using resource, then the following will work
scope '/dashboard' do
resources :users, :only => :show, :module => 'private'
end
the 'rake routes' output is like this
GET /dashboard/users/:id(.:format) private/users#show
the trailing 'show' inside the url is not needed.
namespace "dashboard" do
get "users/:id/show" => "private_users#show"
end

Upgrading routes in Rails 3

Currently I have something like this:
resources :books do
collection do
get 'search'
end
end
and my controller name is also "books" and I have a action method called "search" inside it
I would like that "get search" part to also be a resource, kind of like nested resources... but I don't want to break other peoples codes that are using the current route that this generate, so need to update it in a passive way!
resources :books do
collection do
get 'search'
end
resources :searches
end
...if I'm understanding you correctly, that should be what you want. It won't break other routes, just add new ones.
Run rake routes to make sure you have all the routes you want/need.
Use shallow routes nesting like:
resources :books , :shallow => true do
resources :searches
end
Now you will get the following routes:
/books/1 => books_path(1)
/books/1/searches => books_searches_index_path(1)
/searches/2 => searches_path(2)
Similarly you can get separate routing for defined routes like:
get '(:books)/searches', :to => 'books#index'

Resources