0
votes

I'm trying to setup logic in a rails 4.2.0 app where a person has to confirm their user account before they can login to the site / rails app. Basically, I have a sign up form where a person can input an email / password and their signed up. During this process an email is sent to their address with a confirmation token that should provide a link for them to confirm their account. I'm not exactly sure how to use the confirmation token so it changes a boolean value in the DB from false to true. I'll post what I have implemented so far.

users_controller.rb

    def create
            @user = User.new(user_params)
            if @user.save
                # send confirmation email after user has been created.
                @user.send_confirmation

                session[:user_id] = @user.id
                redirect_to root_url, notice: "Thank you for signing up!"
            else
                render "new"
            end
        end


def confirm
        @user = User.find_by_confirmation_token!(params[:id])
        if @user.update_attributes(confirmed: true)
            redirect_to login_path
        end
    end

confirmation.text.erb

To confirm your account, click the URL below.

<%= user_url(@user.confirmation_token) %>

<%= url_for(controller: 'users', action: 'confirm') %>

If you did not request your account creation, just ignore this email and your account will not be created.

routes.rb

Rails.application.routes.draw do

  resources :articles do
    resources :comments
  end

  get 'resume' => 'resume#index'

  get 'signup' => 'users#new'
  get 'login' =>'sessions#new'
  get 'logout' => 'sessions#destroy'

  # the below route led to a rails routing error
  # get 'confirm' => 'users/:confirmation_token#confirm'

  resources :users
  resources :sessions
  resources :password_resets

  # route to hopefully get confirmation link working :-/
  match '/users/:confirmation_token', :to => 'users#confirm', via: [:post, :get]

  # test route
  match 'users/foo', :to => 'users#foo', via: [:post, :get]

  root "articles#index"

  # Added below route for correct "resumé" spelling
  get 'resumé', :to =>"resume#index"

  # get 'about#index'
  get 'about' => 'about#index'
  get 'contact' => 'contact#contact'

  resources :about
  resources :contact

  match ':controller(/:action(/:id))(.:format)', via: [:post, :get]
1
why not using devise?you can take a look at how they implement confirmable module: rubydoc.info/github/plataformatec/devise/master/Devise/Models/…kasperite

1 Answers

0
votes

I ended up separating the confirmation logic into it's own controller, i.e. away from the users_controller.rb This allowed me to add the following line to my routes.rb

resources :confirmations

which allowed me to edit the confirmation.text.erb and put the following link in the email message,

<%= edit_confirmation_url(@user.confirmation_token) %>

thus when a person receives an email to confirm their account, it routes to the edit action of the confirmation controller, which the edit action calls the update action, and confirms the account. The controller looks like the following,

confirmations_controller.rb

class ConfirmationsController < ApplicationController

    def new
    end

    def edit
        @user = User.find_by_confirmation_token!(params[:id])
        update
    end

    def update
        # @user = User.find_by_confirmation_token!(params[:id])
        if @user.confirmation_sent_at < 2.hours.ago
            redirect_to new_confirmation_path, :alert => "Confirmation has expired."
        # elseif @user.update_attributes(params[:user])
        elsif @user.update_attributes(confirmed: true)
            redirect_to root_url, :notice => "Your account has been confirmed."
        else
            render :new
        end
    end
end