Override Rails Devise Controllers and get routing errors - ruby-on-rails

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

Uninitialized Controller Constant in Ruby on Rails 5

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'

Routing constraints for multiple controllers under top level route

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Ă .

Cannot login/logout with Devise, because "uninitialized constant Users::SessionsController"

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.

Redirect user to Sign In page after Sign Up (registration)

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

Devise custom registrations controller error

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" }

Resources