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.
Related
I am getting a uninitialized constant Project::Controller. I've looked through the Rails docs and posts here on SO, but the code seems to be setup correctly. I am using rails 5.1.1. My pages path works fine, only the root path gives the error.
routes .rb
Rails.application.routes.draw do
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
devise_for :users,
path: '',
path_names: {
sign_in: 'login',
sign_out: 'logout',
edit: 'profile'
},
controllers: { omniauth_callbacks: 'omniauth_callbacks' }
get 'pages/about'
root 'project/#index'
resources :project do
resources :task, only: [:show]
end
end
project_controller.rb
class ProjectController < ApplicationController
def index
#projects = Project.all
end
def show
#project = Project.find(params[:id])
#tasks = #project.tasks
end
end
Change
root 'project/#index'
to
root 'project#index'
I'm looking for some feedback on both the philosophy of good practice and technical practice of using a top level route that routes to multiple Models based on conditions.
I need to have a top level route domain.com/:id that either routes to a: Company or User.
The condition/identifier being that a User has an # in the url, e.g. domain.com/#theminijohn
My routes for the moment look like this:
devise_for :users, path: '',
path_names: {
sign_up: '',
registration: 'signup',
sign_in: 'login',
password: 'password',
confirmation: 'verification'
},
controllers: {
sessions: 'users/sessions',
registrations: 'users/registrations',
omniauth_callbacks: 'users/omniauth_callbacks',
passwords: 'users/passwords'
}
resources :users, path: '', only: [:show] do
member do
get 'reviews', to: 'users#reviews', as: :reviews
get :following, :followers
post :follow, to: 'users#follow_user'
post :unfollow, to: 'users#unfollow_user'
end
end
resources :companies, path: '', only: [:show], as: :company do
resources :products, path: '', only: [:show], as: :product
end
Furthermore the # sign will only be used in the url, aka it is not present in the attribute.
How do I go about this ?
Edit: Here's where I am:
the constraint that gets called from the route for the :users resource
module Constraints
class UserProfile
def matches?(request)
if request.path.include?('#')
slug = request.path.delete('/#')
User.where(slug: slug).exists?
end
end
end
end
and in the controller I patched the find method to:
def set_user
#user = User.includes(:reviews).find(params[:id].delete('#'))
end
How I ended up solving this:
1) Include the # in the friendly_id slug
To do this I had to patch the normalize function which strips it out when calling .parameterize
# overwrite normalize function because it's stripping
# out '#' when calling .parameterize
def normalize_friendly_id(value)
"#" + value.to_s.parameterize
end
2) Regenerate all slugs
There are various methods, I went with deleting the slug and generating it again.
User.each do |u|
u.update_attribute(:slug, nil)
end
User.find_each(&:save)
Have in mind should_generate_new_friendly_id? & if you overwrote it.
3) Routing Constraint
I wrapped my User routes in a constraint:
constraints(Constraints::UserProfile.new) do
resources :users,
....
end
which looks like this:
module Constraints
class UserProfile
def matches?(request)
if request.path.match? /\/#(.*)/
slug = request.path.split('/')[1]
User.where(slug: slug).exists?
end
end
end
end
VoilĂ .
I have following setup in routes.rb:
devise_for :users, path_names: { sign_in: "login", sign_out: "logout" },
controllers: { omniauth_callbacks: "authentications", registrations: "users/registrations", :sessions => "users/sessions" }
devise_scope :user do
... some other routes ...
end
When I try to sign up, log in or log out, I always get a similar error message like this:
Routing Error
uninitialized constant Users::SessionsController
In controllers, I have a folder called users and in this folder is registrations_controller.rb with following content:
class Users::RegistrationsController < Devise::RegistrationsController
def create
super
session[:omniauth] = nil unless #user.new_record?
end
def build_resource(*args)
super
if session[:omniauth]
#user.apply_omniauth(session[:omniauth])
#user.valid?
end
end
end
How to get rid of that error message?
Thank you.
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
When I try to create a custom devise controller:
class RegistrationsController < Devise::RegistrationsController
def new
super
end
def create
# add custom create logic here
end
def update
super
end
end
I get a following error:
Unknown action
AbstractController::ActionNotFound
It is not the problem with routes. I tried to inherit RegistrationsController from ApplicationController and it works fine. As soon as i try to inherit from Devise::RegistrationsController it shows an error. It can't be an action problem to, becuse I tried to create a different action, and I get the same error.
# app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
root :to => "registrations#new"
Using Rails 3.0.4
In your routes you have to use devise_scope if you are overriding devise default actions.
devise_for :users, :controllers => {:registrations => "registrations"}
devise_scope :user do
root :to => "registrations#new"
end
For a similar issue please see http://groups.google.com/group/plataformatec-devise/browse_thread/thread/a5beaaf4b1ad343a
Also here are the docs on changing default sign in routes, I know this you are doing registration, but this could be similar: https://github.com/plataformatec/devise/wiki/How-To:-Change-the-default-sign_in-and-sign_out-routes
I used the following code in my project successfully:
app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
end
routes.rb
devise_for :users, :controllers => { :registrations => "users/registrations" }