7

I having some trouble with editing a user with Devise. The request seems to be getting sent with the correct routes:

Request parameters  
{"controller"=>"users/registrations", "action"=>"edit"}

but I'm getting this error:

NoMethodError in Users::RegistrationsController#edit

undefined method `validatable?' for nil:NilClass

Extracted source (around line #170):

# Sets minimum password length to show to user
  def set_minimum_password_length
    if devise_mapping.validatable? # <- ERROR HIGHLIGHTED HERE
      @minimum_password_length = resource_class.password_length.min
    end
  end

The RegistrationsController is fairly straight forward:

class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]
  before_action :configure_account_update_params, only: [:update]

  # GET /resource/sign_up
  def new
    super
  end

  # POST /resource
  def create
    super
  end

  # GET /resource/edit
  def edit
    super
  end

The view for the edit page:

<h2>Edit <%= resource_name.to_s.humanize %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
  <%= devise_error_messages! %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true %>
  </div>

  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
    <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
  <% end %>

  <div class="field">
    <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
    <%= f.password_field :password, autocomplete: "off" %>

    //deleting this conditional makes no difference.
    <% if @minimum_password_length %>
      <br />
      <em><%= @minimum_password_length %> characters minimum</em>
    <% end %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
    <%= f.password_field :current_password, autocomplete: "off" %>
  </div>

  <div class="actions">
    <%= f.submit "Update" %>
  </div>
<% end %>

<h3>Cancel my account</h3>

<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>

<%= link_to "Back", :back %>

Any help would be appreciated.

Here's the stacktrace as well:

Started GET "/users/edit" for ::1 at 2017-06-22 15:27:00 +0200
Processing by Users::RegistrationsController#edit as HTML
Completed 500 Internal Server Error in 2ms (ActiveRecord: 0.0ms)



NoMethodError - undefined method `validatable?' for nil:NilClass:
  devise (4.3.0) app/controllers/devise_controller.rb:170:in `set_minimum_password_length'
  activesupport (5.0.1) lib/active_support/callbacks.rb:382:in `block in make_lambda'
  activesupport (5.0.1) lib/active_support/callbacks.rb:150:in `block (2 levels) in halting_and_conditional'
  actionpack (5.0.1) lib/abstract_controller/callbacks.rb:12:in `block (2 levels) in <module:Callbacks>'
  activesupport (5.0.1) lib/active_support/callbacks.rb:151:in `block in halting_and_conditional'
  activesupport (5.0.1) lib/active_support/callbacks.rb:454:in `block in call'
  activesupport (5.0.1) lib/active_support/callbacks.rb:454:in `call'
  activesupport (5.0.1) lib/active_support/callbacks.rb:101:in `__run_callbacks__'
  activesupport (5.0.1) lib/active_support/callbacks.rb:750:in `_run_process_action_callbacks'
  activesupport (5.0.1) lib/active_support/callbacks.rb:90:in `run_callbacks'
  actionpack (5.0.1) lib/abstract_controller/callbacks.rb:19:in `process_action'
  actionpack (5.0.1) lib/action_controller/metal/rescue.rb:20:in `process_action'
  actionpack (5.0.1) lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
  activesupport (5.0.1) lib/active_support/notifications.rb:164:in `block in instrument'
  activesupport (5.0.1) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
  activesupport (5.0.1) lib/active_support/notifications.rb:164:in `instrument'
  actionpack (5.0.1) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
  actionpack (5.0.1) lib/action_controller/metal/params_wrapper.rb:248:in `process_action'
  searchkick (2.1.1) lib/searchkick/logging.rb:209:in `process_action'
  activerecord (5.0.1) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
  actionpack (5.0.1) lib/abstract_controller/base.rb:126:in `process'
  actionview (5.0.1) lib/action_view/rendering.rb:30:in `process'
  actionpack (5.0.1) lib/action_controller/metal.rb:190:in `dispatch'
  actionpack (5.0.1) lib/action_controller/metal.rb:262:in `dispatch'
  actionpack (5.0.1) lib/action_dispatch/routing/route_set.rb:50:in `dispatch'
  actionpack (5.0.1) lib/action_dispatch/routing/route_set.rb:32:in `serve'
  actionpack (5.0.1) lib/action_dispatch/journey/router.rb:39:in `block in serve'
  actionpack (5.0.1) lib/action_dispatch/journey/router.rb:26:in `serve'
  actionpack (5.0.1) lib/action_dispatch/routing/route_set.rb:725:in `call'
  warden (1.2.7) lib/warden/manager.rb:36:in `block in call'
  warden (1.2.7) lib/warden/manager.rb:35:in `call'
  rack (2.0.1) lib/rack/etag.rb:25:in `call'
  rack (2.0.1) lib/rack/conditional_get.rb:25:in `call'
  rack (2.0.1) lib/rack/head.rb:12:in `call'
  rack (2.0.1) lib/rack/session/abstract/id.rb:222:in `context'
  rack (2.0.1) lib/rack/session/abstract/id.rb:216:in `call'
  actionpack (5.0.1) lib/action_dispatch/middleware/cookies.rb:613:in `call'
  activerecord (5.0.1) lib/active_record/migration.rb:553:in `call'
  actionpack (5.0.1) lib/action_dispatch/middleware/callbacks.rb:38:in `block in call'
  activesupport (5.0.1) lib/active_support/callbacks.rb:97:in `__run_callbacks__'
  activesupport (5.0.1) lib/active_support/callbacks.rb:750:in `_run_call_callbacks'
  activesupport (5.0.1) lib/active_support/callbacks.rb:90:in `run_callbacks'
  actionpack (5.0.1) lib/action_dispatch/middleware/callbacks.rb:36:in `call'
  actionpack (5.0.1) lib/action_dispatch/middleware/executor.rb:12:in `call'
  actionpack (5.0.1) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
  better_errors (2.1.1) lib/better_errors/middleware.rb:84:in `protected_app_call'
  better_errors (2.1.1) lib/better_errors/middleware.rb:79:in `better_errors_call'
  better_errors (2.1.1) lib/better_errors/middleware.rb:57:in `call'
  actionpack (5.0.1) lib/action_dispatch/middleware/debug_exceptions.rb:49:in `call'
  web-console (3.1.1) lib/web_console/middleware.rb:131:in `call_app'
  web-console (3.1.1) lib/web_console/middleware.rb:28:in `block in call'
  web-console (3.1.1) lib/web_console/middleware.rb:18:in `call'
  actionpack (5.0.1) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
  railties (5.0.1) lib/rails/rack/logger.rb:36:in `call_app'
  railties (5.0.1) lib/rails/rack/logger.rb:24:in `block in call'
  activesupport (5.0.1) lib/active_support/tagged_logging.rb:69:in `block in tagged'
  activesupport (5.0.1) lib/active_support/tagged_logging.rb:26:in `tagged'
  activesupport (5.0.1) lib/active_support/tagged_logging.rb:69:in `tagged'
  railties (5.0.1) lib/rails/rack/logger.rb:24:in `call'
  sprockets-rails (3.2.0) lib/sprockets/rails/quiet_assets.rb:13:in `call'
  actionpack (5.0.1) lib/action_dispatch/middleware/request_id.rb:24:in `call'
  rack (2.0.1) lib/rack/method_override.rb:22:in `call'
  rack (2.0.1) lib/rack/runtime.rb:22:in `call'
  activesupport (5.0.1) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
  actionpack (5.0.1) lib/action_dispatch/middleware/executor.rb:12:in `call'
  actionpack (5.0.1) lib/action_dispatch/middleware/static.rb:136:in `call'
  rack (2.0.1) lib/rack/sendfile.rb:111:in `call'
  railties (5.0.1) lib/rails/engine.rb:522:in `call'
  puma (3.0.0) lib/puma/configuration.rb:221:in `call'
  puma (3.0.0) lib/puma/server.rb:723:in `handle_request'
  puma (3.0.0) lib/puma/server.rb:406:in `process_client'
  puma (3.0.0) lib/puma/server.rb:271:in `block in run'
  puma (3.0.0) lib/puma/thread_pool.rb:111:in `block in spawn_thread'
Ivan
  • 93
  • 1
  • 5
  • Could you post the view that is causing the error please? I believe it may be with how a form is being generated – Mark Jun 22 '17 at 13:34
  • @Mark I've just updated the post with the view. It's simply the default view used by Devise. Thank you! – Ivan Jun 22 '17 at 13:46
  • 1
    Did you ever find an answer to this? Having the same problem – tomb Apr 30 '18 at 20:03

2 Answers2

9

the problem is that devise doesn't know what is the resource that you are using in your custom controllers. So, you need to wrap all routes to your custom controllers with the name of resource, in this way:

  # config/routes.rb

  devise_scope :user do
    root to: 'users/registrations#new'
  end

Source: https://www.rubydoc.info/github/plataformatec/devise/ActionDispatch%2FRouting%2FMapper:devise_scope

Jeisson Rosas
  • 91
  • 1
  • 2
0

I had this issue recently, but it seemed to develop when I moved my route to root 'registrations#new' instead of home#index. Reverting it back fixed it for me.

  • 1
    I have the same situation but I would rather not switch back. It seems we should be able to set our root route to point to "devise/registrations#new". If we use "home#index" and render the devise registration form, we will have to tackle other issues. – wuliwong Apr 20 '19 at 18:00