I'm trying to used devise_token_auth with active_admin. When running rails g active_admin:install User I get the following error.
error
usr/local/lib/ruby/gems/2.4.0/gems/actionpack-5.1.4/lib/action_dispatch/routing/route_set.rb:578:in
add_route': Invalid route name, already in use: 'new_user_session'
You may have defined two routes with the same name using the:as`
option, or you may be overriding a route already defined by a resource
with the same naming.
routes.rb
Rails.application.routes.draw do
devise_for :users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
mount_devise_token_auth_for 'User', at: 'auth'
scope module: 'api' do
namespace :v1 do
resources :users, only: [:index, :show]
end
end
get '/docs' => redirect('/swagger/dist/index.html?url=/apidocs/api-docs.json')
end
can you try a different approach by defining two controllers: one for api and the other for active_admin?
# app/controllers/api_controller.rb
# API routes extend from this controller
class ApiController < ActionController::Base
include DeviseTokenAuth::Concerns::SetUserByToken
end
# app/controllers/application_controller.rb
# leave this for ActiveAdmin, and any other non-api routes
class ApplicationController < ActionController::Base
end
Now inherit all api controllers from ApiController and ActiveAdmin ones from ApplicationController.
There is a known issue between ActiveAdmin and DeviseTokenAuth
I got it working by moving mount_devise_token_auth_for 'User', at: 'auth'
into the api scope. The answer was right , here.
Rails.application.routes.draw do
devise_for :users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
constraints subdomain: 'api'do
scope module: 'api' do
namespace :v1 do
resources :users, only: [:index, :show]
mount_devise_token_auth_for 'User', at: 'auth'
end
end
get '/docs' => redirect('/swagger/dist/index.html?url=/apidocs/api-docs.json')
end
end
Related
I'm overriding Devise controllers in Rails like that:
module Api
module V1
module Devise
class RegistrationsController < Devise::RegistrationsController
....
end
end
end
end
And thats my routes:
Rails.application.routes.draw do
root 'application#index'
devise_for :users
devise_for :taxi_drivers, only: :passwords
resources :taxi_drivers_groups, only: %i[index new create edit update]
namespace :api do
namespace :v1 do
devise_for :users,
defaults: { format: :json },
class_name: 'User',
skip: %i[registrations sessions passwords],
path: '',
path_names: { sign_in: 'login', sign_out: 'logout' }
devise_scope :user do
post 'signup', to: 'devise/registrations#create'
post 'login', to:'devise/sessions#create'
delete 'logout', to: 'devise/sessions#destroy'
post 'password_recover', to: 'devise/passwords#create'
put 'password_recover', to: 'devise/passwords#update'
end
end
end
end
And I'm getting an error when I try to pass my tests:
ActionController::RoutingError: uninitialized constant Api::V1::Devise::RegistrationsController
And in my test file:
test 'user invalid sigup with empty fields' do
#valid_signup_params[:name] = nil
post('/api/v1/signup.json', { user: #valid_signup_params }, headers: { format: :json })
assert_equal last_response.status, 422
assert_equal json_response['errors']['name'].count, 1
end
Do you have any idea how to fix this error?
Thanks!
The issues comes from a constant clash between the newly defined controller and the existing one.
Replacing class RegistrationsController < Devise::RegistrationsController with class RegistrationsController < ::Devise::RegistrationsController is fixing the issue as ruby knows that he has to find the RegistrationsController class in the previously defined Devise module and not in the current definition.
I am trying to implement devise authentication using ajax and jquery. I generated devise controllers using:
rails g devise:controllers users It created all the necessary controller files required such as sessions, registration.
These are the controller files:
class Users::SessionsController < Devise::SessionsController
respond_to :html, :json
end
class Users::RegistrationsController < Devise::RegistrationsController
respond_to :html, :json
end
routes.rb file looks like below:
devise_for :users, controllers: {sessions: 'sessions', registrations: 'registrations'}
As soon as I fill the registration form and hit enter I get:
Routing Error
uninitialized constant RegistrationsController
You're missing the namespace in your routes
devise_for :users, controllers: {
sessions: 'users/sessions',
registrations: 'users/registrations'}
change routes.rb from
devise_for :users, controllers: {sessions: 'sessions', registrations: 'registrations'}
to
devise_for :users, controllers: {sessions: 'users/sessions', registrations: 'users/registrations'}
I experienced this issue when working on a Rails 6 application.
I had my model named application_registration.rb
My views directory was app/views/application_registrations
And my routes was: resources :application_registrations, only: [:create, :update, :new, :edit]
But it was throwing an error:
uninitialized constant ApplicationRegistrationsController Did you mean ApplicationController
Here's how I fixed it:
The issue arose from the naming of my controller.
I had named it application_registrations.rb
All I had to do was to rename it to application_registrations_controller.rb
That's all
I hope this helps
In my question How to have root view when user is not logged in rails? max answered that we can use authenticated to make routes available only when someone is authenticated. I am having a probem that how can I structure this:
Rails.application.routes.draw do
devise_for :users
authenticated :user do
# when authenticated allow all action on student
resources :subjects do
resources :students
end
end
# when not only allow read on student
resources :subjects do
resources :students, only: [:get]
end
root "home#index"
end
The problem is I don't want to allow any unauthenticated action on :subjects how to stop that?
If you want to limit access to subjects you should do it on the controller layer - not in the routes. Using before_action :authenticate_user! will give a 401 Unauthorized response and redirect to the sign in.
class ApplicationController
# secure by default
before_action :authenticate_user!, unless: :devise_controller?
end
class SubjectsController < ApplicationController
# whitelist actions that should not require authentication
skip_before_action :authenticate_user!, only: [:show, :index]
# ...
end
Rails.application.routes.draw do
devise_for :users
resources :subjects do
resources :students
end
root "home#index"
end
Using the authenticated and unauthenticated route helpers are useful when you want the have different responses for the same route for authenticated and unauthenticated users but is not how you should structure your application.
If you simply use authenticated in your routes unauthenticated users will get a 404 Not Found response instead of being prompted to sign in. Which is not helpful.
Also resources :students, only: [:get] does not generate any routes at all. The onlyoption is for limiting the actions (show, index, edit, update ...) not the HTTP method. Use rake routes to see the routes in your app.
Here is the simple way to structure authenticated and unauthenticated routes.
In app/controllers/application_controller.rb, add
"before_action :authenticate_user!".
My app/controllers/application_controller.rb file:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
end
My config/routes.rb:
Rails.application.routes.draw do
devise_for :users
root "home#index"
devise_for :users, controllers: {
:sessions => "users/sessions",
:registrations => "users/registrations" }
authenticated :user do
resources :students
end
unauthenticated :user do
#Some route
end
end
I was trying to build a json api for my application
This is my ROUTES.RB FILE
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
namespace :api , :path =>"", :constraints => {:subdomain =>"api"} , defaults: {format: 'json'} do
namespace :v1 do
resources :posts do
resources :comments
end
end
end
# namespace :v1 do
# resources :posts, only: [:index]
#end
#end
root 'posts#index'
end
and i created another folder under Controller to use namespace
I created "api" folder and under that v1 folder, and under that a posts_controller.rb file
this is exact path
" /app/controllers/api/v1/posts_controller.rb "
class Api::V1::PostsController < ApplicationController
protect_from_forgery with: :null_session
before_action :destroy_session
def index
#posts=Post.all
respond_to do |format|
format.json { render json: #posts}
end
end
private
def destroy_session
request.session_options[:skip]= true
end
end
and i do have data in the postscontroller and associations are also made.
Actually what i need is , when i access this Url http://api.localhost:3000/v1/posts
i need the data in the posts as in json format present in the browser
But its showing this error
No route matches [GET] "/v1/posts"
How can i fix this error ?
You have defined your :posts resources directly, and namespaced it under api > v1. You can access http://api.localhost:3000/posts but you can't access the under v1. You need to add namespace to it like this
namespace :v1 do
resources :posts do
resources :comments
end
end
What you've done is you've namespaced your v1 inside api. You can take the above approach or try accessing like http://api.localhost:3000/api/v1/posts
Update:
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :posts do
resources :comments
end
end
end
#The below part to access everything the regular way(non-api way)
resources :posts do
resources :comments
end
#namespace :v1 do
# resources :posts, only: [:index]
#end
#end
root 'posts#index'
end
Update your routes file to the following. And try accessing these two urls
http://localhost:3000/posts
http://localhost:3000/api/v1/posts
You can not access sub domains in your localhost without extra configuration. So try the new routes code, without constraints in your route.
I am using Devise 3.1.1 and am trying to redirect user to the Sign In page after he signs up.
As instructed in Devise's wiki I overridden RegistrationsController with the following:
class RegistrationsController < Devise::RegistrationsController
protected
def after_inactive_sign_up_path_for(resource)
'/users/sign_in'
end
end
As instructed, I also added the following line to the routes.rb:
devise_for :users, controllers: { registrations: 'registrations'}
After which I get the following error when I go to sign in page:
Invalid route name, already in use: 'new_user_session' You may have defined two routes with the same name using the:asoption, or you may be overriding a route already defined by a resource with the same naming.
In my routes I already have this defined:
devise_for :users, skip: :registrations
devise_scope :user do
resource :registration,
# disabled :edit & :destroy
only: [:new, :create, :update],
path: 'users',
path_names: { new: 'sign_up' },
controller: 'devise/registrations',
as: :user_registration do
get :cancel
end
end
You can only define the devise_for block once, and as you're already messing with the default registrations controller you should be able to just do something like the following to have devise use your controller:
devise_for :users, skip: :registrations
devise_scope :user do
resource :registration,
# disabled :edit & :destroy
only: [:new, :create, :update],
path: 'users',
path_names: { new: 'sign_up' },
controller: 'registrations',
as: :user_registration do
get :cancel
end
end