Created
June 29, 2017 17:40
-
-
Save Genkilabs/587fab4214798c87c3aa97bb06280f43 to your computer and use it in GitHub Desktop.
How to use Devise inside of a Versionist scope without the version-name in the model's path prefix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#/config/initializers/inflections.rb | |
# This is a nice-to-have so API doesn't keep showing up as Api | |
ActiveSupport::Inflector.inflections(:en) do |inflect| | |
inflect.acronym 'API' | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#/config/routes.rb | |
api_version(:module => "API::V1",:path => {:value => "api/v1"}) do | |
devise_for :users, | |
:as => :fancy, #removes "api_v1" from the derived model scope, but it cant be blank so pick something that doesn't contain the version. | |
:path => "", #removes "users" from the path so it is just "api/:ver/login" | |
# Here is where we add a custom, versioned, controller if we want one. It is not necessary though. | |
# :controllers => { :sessions => "api/v1/sessions" }, #routes our session to our custom controller | |
:path_names => { sign_in: 'login', sign_out: 'logout'} #changes the 'action' part of the path name, just flavour. | |
end | |
#if you need a scope, you must now include the scope you choose in devise_for :as. for example: | |
devise_scope :fancy_user do | |
#helper route so we can test with a logout link or url using GET | |
get :logout, :controller => :sessions, :action => :destroy | |
end | |
end |
Hi there, thanks for providing the snippet. However, I am getting an uninitialized constant
issue, have you encounter this issue before?
I did not create any custom controllers for devise. My own controllers work fine living under /api/v1.
Thanks in advance.
config/routes.rb
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
mount Rswag::Ui::Engine => '/api-docs'
mount Rswag::Api::Engine => '/api-docs'
# API version 1
api_version(:module => "API::V1", :path => {:value => "api/v1"}) do
resources :clubs
resources :events
resource :galleries do
resources :images, :only => [:create, :destroy]
end
devise_for :users,
:as => :default,
:path => '',
:path_names => {
sign_in: 'login',
sign_up: 'register',
sign_out: 'logout'
}
end
devise_scope :default_user do
get :logout, :controller => :sessions, :action => :destroy
end
end
** $ rails routes **
➜ rails routes
Prefix Verb URI Pattern Controller#Action
rswag_ui /api-docs Rswag::Ui::Engine
rswag_api /api-docs Rswag::Api::Engine
api_v1_clubs GET /api/v1/clubs(.:format) api/v1/clubs#index
POST /api/v1/clubs(.:format) api/v1/clubs#create
api_v1_club GET /api/v1/clubs/:id(.:format) api/v1/clubs#show
PATCH /api/v1/clubs/:id(.:format) api/v1/clubs#update
PUT /api/v1/clubs/:id(.:format) api/v1/clubs#update
DELETE /api/v1/clubs/:id(.:format) api/v1/clubs#destroy
api_v1_events GET /api/v1/events(.:format) api/v1/events#index
POST /api/v1/events(.:format) api/v1/events#create
api_v1_event GET /api/v1/events/:id(.:format) api/v1/events#show
PATCH /api/v1/events/:id(.:format) api/v1/events#update
PUT /api/v1/events/:id(.:format) api/v1/events#update
DELETE /api/v1/events/:id(.:format) api/v1/events#destroy
api_v1_galleries_images POST /api/v1/galleries/images(.:format) api/v1/images#create
api_v1_galleries_image DELETE /api/v1/galleries/images/:id(.:format) api/v1/images#destroy
api_v1_galleries GET /api/v1/galleries(.:format) api/v1/galleries#show
PATCH /api/v1/galleries(.:format) api/v1/galleries#update
PUT /api/v1/galleries(.:format) api/v1/galleries#update
DELETE /api/v1/galleries(.:format) api/v1/galleries#destroy
POST /api/v1/galleries(.:format) api/v1/galleries#create
new_default_user_session GET /api/v1/login(.:format) api/v1/sessions#new
default_user_session POST /api/v1/login(.:format) api/v1/sessions#create
destroy_default_user_session DELETE /api/v1/logout(.:format) api/v1/sessions#destroy
new_default_user_password GET /api/v1/password/new(.:format) api/v1/passwords#new
edit_default_user_password GET /api/v1/password/edit(.:format) api/v1/passwords#edit
default_user_password PATCH /api/v1/password(.:format) api/v1/passwords#update
PUT /api/v1/password(.:format) api/v1/passwords#update
POST /api/v1/password(.:format) api/v1/passwords#create
cancel_default_user_registration GET /api/v1/cancel(.:format) api/v1/registrations#cancel
new_default_user_registration GET /api/v1/register(.:format) api/v1/registrations#new
edit_default_user_registration GET /api/v1/edit(.:format) api/v1/registrations#edit
default_user_registration PATCH /api/v1(.:format) api/v1/registrations#update
PUT /api/v1(.:format) api/v1/registrations#update
DELETE /api/v1(.:format) api/v1/registrations#destroy
POST /api/v1(.:format) api/v1/registrations#create
logout GET /logout(.:format) sessions#destroy
Routes for Rswag::Ui::Engine:
root GET / rswag/ui/home#index
Routes for Rswag::Api::Engine:
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The need for this arose while combining the excellent tutorial by @trabe on remote authentication in Devise (http://4trabes.com/2012/10/31/remote-authentication-with-devise/), with the need to version this authentication using Versionist. Basically, the problem is that when you nest devise inside the api_version block provided by Versionist, then the path, in this case "api/v1" is added to the actual object scope sent to Warden. So you are no longer authenticating a :user but an :api_v1_user.
What does that really mean? It means that devise methods like
current_user
becomecurrent_api_v1_user
! Of course that is ugly, but it's really going to be a problem as soon as v2 comes out ;)Just remember that since you changed the scope, if you want to do some custom strategy then you would need to reference it that way when you register it with warden. ie. initializers/devise.rb ends up like:
Hope this helps someone, enjoy ^_^