ruby-on-railsrubyruby-on-rails-3authenticationconfirmation-email

Rails - Email sign-up confirmation - NoMethodError


I want an email to be sent when a user registers. This email should contain a link that changes the account to a full user. I want this email link to be a token for security.

Currently: I get the email to send but when I click the link I get this error.

NoMethodError in UsersController#accept_invitation

undefined method `email_activation_token=' for nil:NilClass

Link Sent http://localhost:3000/users/accept_invitation.tLPOjM3hdA13rEv5FNhsOQ

user_controller.rb

class UsersController < ApplicationController
  def new
    @user = User.new
  end
  def create
    @user = User.new(params[:user])
    if @user.save
      UserMailer.registration_confirmation(@user).deliver
        redirect_to root_url, :notice => "Signed up!"
    else
        render "new"
    end

  def accept_invitation
      @user = User.find_by_email_token(params[:email_token])
      @user.email_activation_token = true
      @user.save
      redirect_to root_url, :notice => "Email has been verified."
  end
  end
end

registration_confirmation.html.haml

Confirm your email address please!

= accept_invitation_users_url(@user.email_token)

user.rb model

    class User < ActiveRecord::Base
      attr_accessible :email, :password, :password_confirmation

      attr_accessor :password
      before_save :encrypt_password
      before_save { |user| user.email = email.downcase }
      before_create { generate_token(:auth_token) }
      before_create { generate_token(:email_token) }

      VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
      VALID_PASSWORD_REGEX = /^(?=.*[a-zA-Z])(?=.*[0-9]).{6,}$/
      validates_confirmation_of :password
      validates :password, :on => :create, presence: true, format: { with: VALID_PASSWORD_REGEX }
      validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }

def generate_token(column)
  begin
    self[column] = SecureRandom.urlsafe_base64
  end while User.exists?(column => self[column])
end

end

Solution

  • The problem is in the URL which you are sending out in your email

    http://localhost:3000/users/accept_invitation.tLPOjM3hdA13rEv5FNhsOQ
    

    In the above link, there are no params generated and thus when the first line of the accept_invitation action runs, then @user is set to nil because there are no params[:email_token].

    According to me, you should set your link something like

    registration_confirmation.html.haml

    Confirm your email address please!
    
    = accept_invitation_users_url(:email_token => @user.email_token)
    

    in your mailer view