Scope and Namespace routes in Rails - ruby-on-rails

I'm following a tutorial on Dookeeper and Devise gems in Rails, in one point of the video, the author creates the following routes:
namespace :api do
namespace :v1 do
resources:books
end
end
scope :api do
scope :v1 do
use doorkeeper do
skip_controllers:authorizations,:applications,:authorized_applications
end
end
end
I don't quite understand what's the point of the namespace and scope in point... They complement each other or are separated things and why do I have to use?
Thanks a lot!

Here's a helpful overview.
In short (my emphasis added):
When you use namespace, it will prefix the URL path for the specified resources, and try to locate the controller under a module named in the same manner as the namespace.
When using scope without any options and only a scope name, it will just change the resources path.
So scope is useful for making a route match namespace when there aren't controllers with matching names.
namespace :api do
namespace :v1 do
resources:books
end
end
Gives you a base route of "/api/v1/books" but requires a Api::V1::BooksController
scope :api do
scope :v1 do
use doorkeeper do
skip_controllers:authorizations,:applications,:authorized_applications
end
end
end
Gives doorkeeper routes that start with "api/v1" but without trying to match to an Api::V1::Doorkeeper class.

Related

how to add namespace to route file using custom generators

I am generating certains controllers using rails generators, it is working as expected.
However, how can i add namespace based routes in my route file
something like
namespace :api do
namespace :v1 do
get resource_one, to: resource_one_index
get resource_two, to: resource_two_index
end
end
I see the following in the documenation under the route section route "resources :people" but i am not sure how to add namespace routing.
Thanks.

Resource in and outside namespace

I have the following routes.rb:
resources :users
namespace :vmt do
resources :dashboards do
resources :users
resources :evaluation_units
resources :orga_units
end
end
I want to set the user in an overall context and nested in a single dashboard context within a namespace. The users-Controller is not in the namespace. So when I open the path /vmt/dashboards/1/users in browser, I get the following Routing Error
uninitialized constant Vmt::UsersController
So how can I specify, that in this resource
namespace :vmt do
resources :dashboards do
resources :users
that the controller is not in a namespace? I tried to set the controller explecitly with
resources :users, controller: 'user'
but it's still in the vmt namespace.
Using scopes will point rails to the proper url, but does not seem to provide the same useful route url helpers. We can, however, use / to point to the 'top level' controller.
Say you have two routes we want to display the users on:
/users and /admin/users
resources: users
namespace :admin do
resources :users, controller: '/users' # 'users' alone would look for a '/admin/users_controller'
end
With this, we can continue to use the url helper admin_users_path
(Note: Not a rails expert, there may be a way to create url helpers for scopes, or some other solution. Above tested on rails 5.2)
My original answer didn't work in the end, once you're inside a namespaced scope within a route you can't get out anymore.
The easiest way to re-use your logic is to create a Vmt::UsersController like so:
class Vmt::UsersController < ::UsersController
end
You can specify a different module with the module key.
For example:
resources :users, module: nil
Edit: I'm not 100% sure if this will work inside a namespace. If not, you can change it to a scope, and add the module explicitly to the other resources.

How to have one resource in routes for namespace and root path altogether - Rails 4

I am making a custom admin panel in a namespace "admin".
I have resources "courses" within that namespace.
But I would also like a route to "courses" that is not in that namespace:
eg: BOTH localhost:3000/admin/courses AND localhost:3000/courses
It's OK if this requires different controllers.
My concern is that its not really DRY if i have both resources for the same route.
namespace admin do
resources :courses
end
and just
resources :courses
Is there a way to have one resource be shared between namespace and without namespace, or is the example above the way to go?
Oh wait ! There's also the possibility to use concerns !
concern :shared_actions do
resources :courses
resources :something_else
end
namespace :admin do
concerns :shared_actions
end
concerns :shared_actions # Will add it to the root namespace ^^
EDIT : apparently this is what this guy also tried to do :D
I'm not really sure I understand what you mean, but
namespace :something is actually a shorthand for scope :something, module: :something, as: :something
scope :something will add /something/ as a URL prefix
scope module: :something will add /something as a controller prefix (controllers will be fetched under controlelrs/something/the_controller.rb
scope as: :something will add the something as a prefix for path helpers
Now it's totally fine to have both in your routes
resources :courses
# Will generate "/courses/", "/courses/new", "/courses/1/edit", ...
# And will point to `controllers/courses_controller.rb`
namespace :admin do
resources :courses
end
# Will generate "/admin/courses/", "/admin/courses/new", "/admin/courses/1/edit", ...
# And will point to `controllers/admin/courses_controller.rb`
Does this answer your question ?

Prevent a route from matching on the wrong namespace?

I have an API with an admin namespace that has many of the same routes as the parent namespace:
App::Application.routes.draw do
namespace :api do
resources :posts
namespace :admin do
resources :posts
end
end
end
Whenever I try to navigate to /api/admin/posts, I hit the controller action for /api/posts.
Is it possible to prevent matching the first route when I am in fact trying to hit the admin namespace?

Rails routing resource in namespace starting with a parameter

I have 2 namespaces, api and v1
I have accounts and users as resources.
I want to map the routing as follows for all my resources:
/api/v1/:account_id/:resource/:id
i.e:
/api/v1/1/users/2
In the example 1 stands for account id and 2 stands for user id.
How do I accomplish this?
This does away with namespaces, such that you don't need to append API::V1:: to each controller, or bury view files in subdirectories. The following uses normal, top-level controllers and views:
scope '/api/v1/:id', :as => 'account' do
resources :users
end
If you want to keep all the namespace structure stuff, do this:
namespace 'api' do
namespace 'v1' do
scope '/:id', :as => 'account' do
resources :users
end
end
end

Resources