0

I think I have a routing issue with Devise that I can't figure out. I am trying to implement this method for having users sign up using Devise for authentication. The example uses haml, and I have attempted to translate that back to erb, hopefully with some success.

Rails 3.2.8 in development on Mac OS X, using PostgresQL Using Devise and simple_form

app/views/devise/registrations/new.html.erb:

<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%# simple_form_for([:backend, @user]) do |f| %>
  <%= f.error_notification %>

  <div class="inputs">
    <%= f.input :email, :required => true, :autofocus => true, :label => "Email" %>
  </div>

  <div class="actions">
    <%= f.button :submit, "Add User" %>
  </div>
<% end %>

app/views/devise/confirmations/show.html.erb:

<%= simple_form_for(resource, :as => resource_name, :url => confirmation_path(resource_name)) do |f| %>
<div class="inputs">
    <%= f.input :password, :required => true, :label => "Password" %>
    <%= f.input :password_confirmation, :required => true, :label => "Confirm Password" %>
    <%= f.hidden_field :confirmation_token %>
</div>
<div class="actions">
  <%= f.button :submit, "Confirm" %>
</div>
<% end %>

app/modesl/user.rb:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable,
         :timeoutable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email,
                  :password,
                  :password_confirmation,
                  :remember_me,
                  :username

  def password_required?
    super if confirmed?
  end

  def password_match?
    self.errors[:password] << "can't be blank" if password.blank?
    self.errors[:password_confirmation] << "can't be blank" if password_confirmation.blank?
    self.errors[:password_confirmation] << "does not match password" if password != password_confirmation
    password == password_confirmation && !password.blank?
  end

end

app/controllers/confirmations_controller.rb:

class ConfirmationsController < Devise::ConfirmationsController
  def show
    self.resource = resource_class.find_by_confirmation_token(params[:confirmation_token])
    super if resource.confirmed?
  end

  def confirm
    self.resource = resource_class.find_by_confirmation_token(params[resource_name][:confirmation_token])
    if resource.update_attributes(params[resource_name].except(:confirmation_token)) && resource.password_match?
      self.resource = resource_class.confirm_by_token(params[resource_name][:confirmation_token])
      set_flash_message :notice, :confirmed
      sign_in_and_redirect(resource_name, resource)
    else
      render :action => "show"
    end
  end
end

app/config/routes.rb:

  devise_for :users, :controllers => {:confirmations => 'confirmations'}

  devise_scope :user do
    put "/confirm" => "confirmations#confirm"
  end

  resources :users

When I input my email address at the users/sign_up page, everything works fine. I receive the confirmation email, click the confirmation link and am directed to:

/users/confirmation?confirmation_token=[CONFIRMATION TOKEN HERE]

Then, when I fill in my password and submit, I am directed to this page:

users/confirmation

with the following error:

ActiveRecord::RecordNotFound in UsersController#update Couldn't find User with id=confirmation

I'm pretty sure it's a routing issue. Any ideas? Thanks so much!

Gruntled
  • 143
  • 9
  • There seems to be a problem with the redirect, just a shot in the dark but can you try changing the url in your simple_form_for to ` :url => confirmation_path(resource)` – Noz Nov 14 '12 at 20:49
  • Thanks for the suggestion but that did not work. Just to be clear, you suggest changing this line, in views/devise/confirmations/show.html.erb: – Gruntled Nov 15 '12 at 00:38
  • <%= simple_form_for(resource, :as => resource_name, :url => confirmation_path(resource_name)) do |f| %> to this: <%= simple_form_for(resource, :as => resource_name, :url => confirmation_path(resource)) do |f| %>? It seems to me that the confirmations controller is never getting invoked. Instead, rails is routing to the show action in the users controller, which is where the error is? – Gruntled Nov 15 '12 at 00:40
  • You can try dropping a `debugger` statement in your confirm action as a breakpoint to make sure it's being invoked. If for whatever reason you don't have debugging setup there's also the option of tossing in garbage code and seeing if you trigger an exception. Also make sure that `render :action => "show"` inside your confirm action is rendering the show action of the confirmation controller and not the users controller. – Noz Nov 15 '12 at 01:13

1 Answers1

0

Cyle, thanks for getting my brain working this evening. The answer was staring me right in the face the whole time. In routes, I changed

match "/confirm" => "confirmations#confirm"

to

match "/confirmation" => "confirmations#confirm"

Now I can start researching the next error it throws. Thanks again!

Gruntled
  • 143
  • 9