0

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.

Community
  • 1
  • 1
Eric deRiel
  • 420
  • 3
  • 14

1 Answers1

3

So one solution appears to be to add

  devise_scope :user do
    get '/users/new' => 'registrations#new'
  end

into routes.rb. This may not be the best answer but it works.

Eric deRiel
  • 420
  • 3
  • 14