I'm trying to create a namespaced API in rails and am running into an issue
# Resources
resources :users do
resources :contacts
end
#==========================================>
# API namespacing and routing
#==========================================>
namespace :api do
namespace :v1 do
# =======================>
# Resources -> Users
# Resources -> Contacts
# =======================>
resources :users do
resources :contacts
end
# =======================>
# Resources -> Messages
# Resources -> Transcriptions
# =======================>
resources :messages do
resources :transcriptions
end
end
end
I want to have my html-responding version of the resource outside of the 'api' namespace (i.e. in the regular app/controllers/users_controller.rb area) but my json-responding inside the namespace.
However when I point my url at the "/api/v1/users.json" link it utilizes the controller specified by the OUTSIDE resources app/controllers/users_controller rather than the one I put in app/controllers/api/v1/users_controller.
Am I only allowed one resources reference despite it being namespaced differently?
Why exactly is this happending
Your routing definitions look ok. The first thing I'd check is what routes are generated by your rails router by running:
$ bundle exec rake routes | grep users
You should have your defined users routes mapped to their respective URL structure. If something's amiss then your routes aren't probably defined correctly. Which i doubt in your case.
Another possible issue might be your controller class name in your namespaced users controller. So your users controller under app/controllers/api/v1 should be
class Api::V1::UsersController < ApplicationController
....
end
Look at the Rubygems.org source which has the same kind of structure you're trying to implement.
your controller should look like
module Api::V1
class UserController < ActionController::Base
...
end
end
Related
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.
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 ?
I was reading Rails routes guide and came to this part:
If you want to route /posts (without the prefix /admin) to Admin::PostsController, you could use:
scope module: 'admin' do
resources :posts, :comments
end
Ok I understood this part, it says if we use scope the way it shows us, instead of for example /admin/posts we can directly say /posts
But I didn't underatand the second part below: What does this one do?
If you want to route /admin/posts to PostsController (without the Admin:: module prefix), you could use:
scope '/admin' do
resources :posts, :comments
end
How about this:
Use if you want to have controller in namespace ONLY, but don't want namespaced url for this controller
Use if you want namespaced url ONLY but not controller
I am using Rocket_Pants gem to provide API access for my existing Rails app. I have two of controllers with the same name but stored in different locations:
I store the controller that handles HTTP requests in app/controllers, and the controller that handles API calls in sub-directory API of app/controllers.
I have the following in my Routes:
# HTTP routing
resources :posts do
collection do
get 'search'
end
end
# API routing
api :version => 1 do
resources :posts, :only => [:index, :show]
resources :posts do
collection do
get 'search'
end
end
end
However, when I rake routes, I got:
GET /:version/posts/search(.:format) posts#search {:version=>/(1)/, :format=>"json"}
GET /:version/posts(.:format) posts#index {:version=>/(1)/, :format=>"json"}
GET /:version/posts/:id(.:format) posts#show {:version=>/(1)/, :format=>"json"}
This means that my API routes are actually pointing to http controller and not API controller. How can I point my API routes to API/posts#search instead?
Given this is your 2nd question tonight on the basics of Rails routing, I strongly recommend reading the Rails Guide on the topic.
For this issue, you're looking for a scope. This is explained in the guide above.
api version: 1 do
scope module: "api" do
resources :posts, only: [:index, :show] do
collection do
get 'search'
end
end
end
end
Also
Your directory should be named app/controllers/api, not app/controllers/API
Your controller should be at app/controllers/api/posts_controller.rb with class name like class Api::PostsController < ApplicationController
I should also mention, I don't know or use rocket_pants, but their README suggests namespacing controllers for different versions in modules as well (another level of scoping above).
Better "pants rockety" answer.
routes.rb
api :version => 1, module: "api" do
resources :foobars
folder structure
-controllers
-api
foobars_controller.rb
etc
api_controller.rb
class ApiController < RocketPants::Base
foobars_controller.rb
class Api::EventsController < ApiController
version 1
etc
I will build a admin interface for my aplication back-end.
I am using Mongoid, and I want to know What is the best for make my own Backend Interface.
I can not use active_admin because it does not works for mongoid odm.
I have in my routes:
devise_for :admins
namespace :admin do
resources :categories
resources: users
resources: posts
.
.
.
end
I have in my controller categories for example:
class Admin::CategoriesController < ApplicationController
before_filter :authenticate_admin! # assuming you're using devise
def index
#etc.
end
end
Its better use namespace or resources?
which is best practice to create an interface for the administrator with others odms or database without using gems as active_admin, rails_admin, typus...etc
Use namespace but remember this:
Do not use the same word as namespace and resources
namespace :admin
resources :categories
end
is fine as long as you don't have a model resource named admin or admins. Otherwise, you will have a hard time debugging or constructing the proper routes( admin_foo_bar_path, can refer either admin namespace or admin resource, which confuses both you and rails ).