How to use namespace in rails without namespace in url - ruby-on-rails

I have a question about routes in rails when using namespaces.
Example code:
namespace :api do
# /api/... Api::
namespace :v1 do
devise_for :users, :controllers => {sessions: 'api/v1/users/sessions', :registrations => "api/v1/users/registrations", :password => 'api/v1/users/passwords'}
resources :events do
namespace :informations do
resources :agendas
resources :attendees
resources :polls
resources :presentatios
resources :speakers
resources :sponsors
resources :votes
resources :vote_options
end
end
end
end
I check my url in console with grep agenda, and it results in:
/api/v1/events/:event_id/informations/agendas
How can I remove namespace information from url without removing namespace from routes?

You can use the module option to add a namespace (as in a module wrapping) to the controllers:
resources :events, module: 'v1/api'
Prefix Verb URI Pattern Controller#Action
events GET /events(.:format) v1/api/events#index
POST /events(.:format) v1/api/events#create
new_event GET /events/new(.:format) v1/api/events#new
edit_event GET /events/:id/edit(.:format) v1/api/events#edit
event GET /events/:id(.:format) v1/api/events#show
PATCH /events/:id(.:format) v1/api/events#update
PUT /events/:id(.:format) v1/api/events#update
DELETE /events/:id(.:format) v1/api/events#destroy
But it makes no sense to use a versioned API controller without versioned urls! That is unless you believe in either using a custom request header or custom accept type. Both of which had some diehard REST purist followers but are now scarce due to the the fact that they are just too dang difficult to test.
http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html

Related

No route matches [PUT], resource and method are defined though

I'm using postman to make a PUT or PATCH request, but it says No route matches [PUT] "/api/registrations"
my URL looks like this
http://localhost:3000/api/registrations?id=5&status=approved"
My routes.rb file:
Rails.application.routes.draw do
scope :api do
resources :professors
resources :registrations
resources :schedules
resources :notifications
resources :users
resources :meetings
resources :courses
resources :students
end
end
I have a defined update method in my RegistrationsController and My POST and GET routes work.
The URL you're using is incorrent. You should not pass id in query, but in path.
A correct URL is
http://localhost:3000/api/registrations/5?status=approved
Rails sets id as last element of a resourceful route.
Docs say:
resources :photos
(...)
PATCH/PUT /photos/:id photos#update update a specific photo
Run rails routes on the command line to get the proper URL pattern and it's matching Controller action.

Custom actions using devise

Background:
The Rails 4 application I am working on has differing logic for API and web registrations, and part of this logic makes their integration extremely difficult. To that end, I'm attempting to separate the routes to deal with issues arising from inheritance, new reCAPTCHA gem, and new logic. (both actions call registrations#create after their respective logic.) I've solved most of the issues arising from separating these two; however, getting the routes working has proven difficult as well.
I'd greatly appreciate any help!
Desired Result:
I'm trying to define a route to a custom action using Devise, and prevent it from creating the default route as well. I've gotten one of them working, but not the second. Here's the excerpt from my routes.rb:
Registry::Application.routes.draw do
devise_for :user,
controllers: {
passwords: 'users/passwords',
sessions: 'users/sessions',
registrations: 'users/registrations'
}
devise_scope :user do
post 'users', to: 'users/registrations#custom_one'
end
# ...
namespace :api do
namespace :v1 do
# ...
devise_scope :user do
post 'users', to: 'registrations#custom_two'
end
end
end
end
Issues:
The issue is that this code generates two nearly-identical routes. Excerpt from rake routes:
user_registration POST /users(.:format) users/registrations#create
users POST /users(.:format) users/registrations#custom_one
api_v1_users POST /api/v1/users(.:format) api/v1/registrations#custom_two
I also want the custom route to have the correct prefix/route name (user_registration), though I've been unable to do this.
I've found plenty of documentation on custom names for Devise routes, but not for custom actions. Especially not when using devise_for.
To summarize:
I need to disable the default users/registrations#create route
and specify a route to a custom action (users/registrations#custom_one)
with the correct prefix/name (user_registration)
hopefully as elegantly as possible, as I would rather avoid specifying each route independently.
You can achieve this by using the :skip option to devise_for:
devise_for :users, :skip => [:registrations] do
get "/admin" => "devise/registrations#new", :as => :new_user_registration
post "/admin" => "devise/registrations#create", :as => :user_registration
end

scope in rails routes not prepending paramter in URL

I have a requirement that I have to append abc/admin in each url. for e.g.
http://0.0.0.0:3000/abc/admin/admins/sign_in # USING ADMIN AS DEVISE MODEL
http://0.0.0.0:3000/abs/admin/products
http://0.0.0.0:3000/abs/admin/products/:id
http://0.0.0.0:3000/abs/admin/categories
etc. Now I tried with
scope "abc/admin" do
resources :products, :categories
end
It creates some URL eg:
products GET /abc/admin/products(.:format) products#index
POST /abc/admin/products(.:format) products#create
new_role GET /abc/admin/products/new(.:format) products#new
for Admin Model I tried using
scope "abc/admin" do
devise_for :admins, :controllers => {:sessions=>"admin/sessions", :registrations=>'admin/registrations'}
end
It also create URL like:
admin_registration POST /abc/admin/admins(.:format) admin/registrations#create
new_admin_registration GET /abc/admin/admins/sign_up(.:format) admin/registrations#new
Now new_admin_registration_path redirect to http://0.0.0.0:3000/admins/sign_up It is not considering the scope. I don't know how to achieve scope parameter in URL for devise as well as for other controller.
#Choco is right, you should only declare a namespace once. Then everything goes inside that single block.
namespace "abc/admin" do
resources :products, :categories
devise_for :admins, :controllers => {:sessions=>"admin/sessions", :registrations=>'admin/registrations'}
end
Then your path helper becomes new_abc_admin_admin_registration_path. See here for info: difference between scope and namespace of ruby-on-rails 3 routing

Rails routes index for nested resource

I'm searching a reason why rake routes doesn't match the index path of my nested resource.
Here is my code:
namespace :api do
resources :photos do
resource :comments
end
end
Here is the result of the command: rake routes | grep comment
batch_action_admin_user_comments POST /admin/user_comments/batch_action(.:format) admin/user_comments#batch_action
admin_user_comments GET /admin/user_comments(.:format) admin/user_comments#index
POST /admin/user_comments(.:format) admin/user_comments#create
new_admin_user_comment GET /admin/user_comments/new(.:format) admin/user_comments#new
edit_admin_user_comment GET /admin/user_comments/:id/edit(.:format) admin/user_comments#edit
admin_user_comment GET /admin/user_comments/:id(.:format) admin/user_comments#show
PATCH /admin/user_comments/:id(.:format) admin/user_comments#update
PUT /admin/user_comments/:id(.:format) admin/user_comments#update
DELETE /admin/user_comments/:id(.:format) admin/user_comments#destroy
admin_comments GET /admin/comments(.:format) admin/comments#index
POST /admin/comments(.:format) admin/comments#create
admin_comment GET /admin/comments/:id(.:format) admin/comments#show
api_photo_comments POST /api/photos/:photo_id/comments(.:format) api/comments#create
new_api_photo_comments GET /api/photos/:photo_id/comments/new(.:format) api/comments#new
edit_api_photo_comments GET /api/photos/:photo_id/comments/edit(.:format) api/comments#edit
GET /api/photos/:photo_id/comments(.:format) api/comments#show
PATCH /api/photos/:photo_id/comments(.:format) api/comments#update
PUT /api/photos/:photo_id/comments(.:format) api/comments#update
DELETE /api/photos/:photo_id/comments(.:format) api/comments#destroy
I tried to add only: [:create, :index] to my comments resource but only the create route is visible.
According to the documentation about nested-resources I don't understand what's happening.
Thank you for your help.
It's because you are using a singular resource (resource :comments)
From the docs:
Sometimes, you have a resource that clients always look up without
referencing an ID. For example, you would like /profile to always show
the profile of the currently logged in user. In this case, you can use
a singular resource to map /profile (rather than /profile/:id) to the
show action
You'll need to use the standard resources method to get this working (resource omits the index action):
#config/routes.rb
namespace :api do
resources :photos do
resources :comments
end
end
My mistake. A "S" was missing on my resource.
namespace :api do
resources :photos do
resources :comments
end
end
Now it works.

difference between scope and namespace of ruby-on-rails 3 routing

I can't understand what the difference is between a namespace and a scope in the routing of ruby-on-rails 3.
Could someone please explain?
namespace "admin" do
resources :posts, :comments
end
scope :module => "admin" do
resources :posts, :comments
end
The difference lies in the paths generated.
The paths are admin_posts_path and admin_comments_path for the namespace, while they are just posts_path and comments_path for the scope.
You can get the same result as a namespace by passing the :name_prefix option to scope.
examples always help me, so here is an example:
namespace :blog do
resources :contexts
end
will give us the following routes:
blog_contexts GET /blog/contexts(.:format) {:action=>"index", :controller=>"blog/contexts"}
POST /blog/contexts(.:format) {:action=>"create", :controller=>"blog/contexts"}
new_blog_context GET /blog/contexts/new(.:format) {:action=>"new", :controller=>"blog/contexts"}
edit_blog_context GET /blog/contexts/:id/edit(.:format) {:action=>"edit", :controller=>"blog/contexts"}
blog_context GET /blog/contexts/:id(.:format) {:action=>"show", :controller=>"blog/contexts"}
PUT /blog/contexts/:id(.:format) {:action=>"update", :controller=>"blog/contexts"}
DELETE /blog/contexts/:id(.:format) {:action=>"destroy", :controller=>"blog/contexts"}
Using scope...
scope :module => 'blog' do
resources :contexts
end
Will give us:
contexts GET /contexts(.:format) {:action=>"index", :controller=>"blog/contexts"}
POST /contexts(.:format) {:action=>"create", :controller=>"blog/contexts"}
new_context GET /contexts/new(.:format) {:action=>"new", :controller=>"blog/contexts"}
edit_context GET /contexts/:id/edit(.:format) {:action=>"edit", :controller=>"blog/contexts"}
context GET /contexts/:id(.:format) {:action=>"show", :controller=>"blog/contexts"}
PUT /contexts/:id(.:format) {:action=>"update", :controller=>"blog/contexts"}
DELETE /contexts/:id(.:format) {:action=>"destroy", :controller=>"blog/contexts"}
Here is some good reading on the subject: http://edgeguides.rubyonrails.org/routing.html#controller-namespaces-and-routing
from the rails guide
"The namespace scope will automatically add :as as well as :module and :path prefixes."
so
namespace "admin" do
resources :contexts
end
is the same as
scope "/admin", as: "admin", module: "admin" do
resources :contexts
end
Both scope and namespace are scoping a set of routes to the given default options.
Except that there are no default options for scope, and for namespace
:path, :as, :module, :shallow_path and :shallow_prefix options all default to the name of the namespace.
Available options for both scope and namespace correspond to those of match.
scope is bit complex, but provides more options to fine-tune exactly what you want to do.
scope supports three options: module, path and as. If you see scope with all it options, it will be exactly same as namespace.
In other words, routes generated by
namespace :admin do
resources :posts
end
is same as
scope module: 'admin', path: 'admin', as: 'admin' do
resources :posts
end
In other words, we can say that there are no default options for scope as compared to namespace. namespace add all these options by default. Thus using scope, we can more fine tune the routes as required.
If you take a deep look into scope and namespace default behaviour, you will find that scope by default supports only :path option, where as namespace supports three options module, path and as by default.
For more info, please refer a doc namespace-and-routing.

Resources