Search code examples
ruby-on-railsrubyruby-on-rails-3devisedevise-confirmable

Devise email only signup


I'm using Rails 4 and Devise 3.2.3. In my app I'm trying to have a logged-in admin user that can create new users with email only.

I followed the instructions here:

https://github.com/plataformatec/devise/wiki/How-To:-Email-only-sign-up

views > confirmations > show.html.haml

%h2 You're almost done! Now create a password to securely access your account.
= semantic_form_for(resource, :as => resource_name, :url => confirm_path) do |form|
= devise_error_messages!
= form.inputs do
= form.input :password, :input_html => {:autofocus => true}
= form.input :password_confirmation
= form.input :confirmation_token, :as => :hidden
= form.actions do
= form.action :submit, :label => 'Confirm Account

confirmations_controller

class ConfirmationsController < Devise::ConfirmationsController

  def show
    self.resource = resource_class.find_by_confirmation_token(params[:confirmation_token]) if params[:confirmation_token].present?
    super if resource.nil? or resource.confirmed?
  end


  def confirm
    self.resource = resource_class.find_by_confirmation_token(params[resource_name][:confirmation_token]) if params[resource_name][:confirmation_token].present?
     if resource.update_attributes(params[resource_name].except(:confirmation_token).permit(:email, :password, :password_confirmation)) && 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

But in my confirmation show action I get this error:

First argument in form cannot contain nil or be empty:
= semantic_form_for(resource, :as => resource_name, :url => confirm_path) do |form|

UPDATE

The issue seems to be with the ConfirmationsController, the show action seems not to work:

The resource method doesn't seem to work. Trying to outputting it with

class ConfirmationsController < Devise::ConfirmationsController

  def show
    self.resource = resource_class.find_by_confirmation_token(params[:confirmation_token]) if params[:confirmation_token].present?
    # super if resource.nil? or resource.confirmed?

    render text: self.resource.nil?
  end

end

returns true

Also the confirmation_token I received by "send_confirmation_instructions" does not belong to any user instance in the database.


Solution

  • I found the solution, the documentation at at the Devise Wiki was incorrect.

    Here is the proper code for Rails 4:

    class ConfirmationsController < Devise::ConfirmationsController
    
      def show
        @original_token = params[:confirmation_token]
        digested_token = Devise.token_generator.digest(self, :confirmation_token,params[:confirmation_token])
    
        self.resource = resource_class.find_by_confirmation_token(digested_token) if params[:confirmation_token].present?
        super if resource.nil? or resource.confirmed?
    
      end
    
    
      def confirm
    
        digested_token = Devise.token_generator.digest(self, :confirmation_token, params[resource_name][:confirmation_token])
        self.resource = resource_class.find_by_confirmation_token(digested_token) if params[resource_name][:confirmation_token].present?
        if resource.update_attributes(params[resource_name].except(:confirmation_token).permit(:email, :password, :password_confirmation)) && 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
    

    Here is the correct views > confirmations > show.html.haml

    %h2 You're almost done! Now create a password to securely access your account.
    = semantic_form_for(resource, :as => resource_name, :url => confirm_path, :method => :patch) do |form|
      = devise_error_messages!
      = form.inputs do
        = form.input :password, :input_html => {:autofocus => true}
        = form.input :password_confirmation
        = form.input :confirmation_token, :as => :hidden, :value => @original_token
      = form.actions do
        = form.action :submit, :label => 'Confirm Account'