I have been building devise into a small Rails app. It's a pretty standard setup but one wrinkle is that the default authentication rules need to be changed for this project. Non-idempotent registration actions must all be restricted to only authenticated users.
To do this, I've written a custom registrations controller and linked it up in the routing. All the custom controller really has to do is alter the filtering requirements. Based on the Rails controller filtering documentation, I got this working with a minimum of effort.
But by itself that only applies to devise-specific actions like /users/sign_up or /users/edit. I would also like to wire in the standard Rails actions (/users/new, /users/1/edit, etc) to the custom controller. I can get the action to instantiate the controller -- leading the horse to water so to speak -- but when the action is new instead of sign_up, it crashes out during the filtering.
The problem appears to be that resource_name yields nil when the action is 'new', but is fine when it's 'sign_up'. I don't understand why devise cares or where the distinction is represented in code. I've looked at other questions like Update the User controller of devise and Override devise registrations controller and Custom Devise controller but they don't get into this issue.
The specific error I am getting is
NoMethodError in RegistrationsController#new
undefined method `name' for nil:NilClass
and the top of the trace is
devise (2.1.2) app/controllers/devise_controller.rb:22:in
resource_name' app/controllers/registrations_controller.rb:104:in
authenticate_scope!'
It is apparently happening the first time devise_mapping is referenced. But as per the above stackoverflow question I have also explicitly provided helpers for devise_mapping, and they don't even get called.
Can anyone explain or help me figure out where to look further?
from routes.rb:
Fs::Application.routes.draw do
devise_for :users, :controllers => { :registrations => 'registrations' }
resources :users, :except => [:index, :show], :controller => 'registrations'
resources :users, :only => [:index, :show]
[...]
rake routes reports:
new_user_session GET /users/sign_in(.:format) devise/sessions#new
user_session POST /users/sign_in(.:format) devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
user_password POST /users/password(.:format) devise/passwords#create
new_user_password GET /users/password/new(.:format) devise/passwords#new
edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
PUT /users/password(.:format) devise/passwords#update
cancel_user_registration GET /users/cancel(.:format) registrations#cancel
user_registration POST /users(.:format) registrations#create
new_user_registration GET /users/sign_up(.:format) registrations#new
edit_user_registration GET /users/edit(.:format) registrations#edit
PUT /users(.:format) registrations#update
DELETE /users(.:format) registrations#destroy
users POST /users(.:format) registrations#create
new_user GET /users/new(.:format) registrations#new
edit_user GET /users/:id/edit(.:format) registrations#edit
user PUT /users/:id(.:format) registrations#update
DELETE /users/:id(.:format) registrations#destroy
GET /users(.:format) users#index
GET /users/:id(.:format) users#show
my registrations_controller.rb:
class RegistrationsController < Devise::RegistrationsController
prepend_before_filter :authenticate_scope!, :except => [:index, :show]
skip_filter :require_no_authentication
end
my users_helper.rb:
module UsersHelper
# used by devise
def resource_name
:user
end
def resource
@resource ||= User.new
end
def devise_mapping
@devise_mapping ||= Devise.mappings[:user]
end
end
using:
Rails 3.2.6
Ruby 1.9.3
devise 2.1.2
Update: pasted in the correct trace output.