0
votes

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!

1
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
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
<%= 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
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

1 Answers

0
votes

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!