Search code examples
deviseresourcesruby-on-rails-5user-registrationemail-confirmation

Devise super do with current record in user controller for sending mails in Ruby on Rails


I'm trying to set up a registration confirmation through email for the users. I'm using devise for authentication. But I could'nt access the saved user resource from the devise controller, though I tried a few tinkers in futile. If some Could lend a helping head, that's great!!!

I'm trying to send a confirmation link to the registered user after the user got saved. But I could not grab the new user records as any usual instance variable in the devise controller.

Now my user registrations controller looks like this:

class Users::RegistrationsController < Devise::RegistrationsController
  before_action :select_plan, only: :new
  # Extend the default Devise gem behaviour so that 
  # the users signing up with a Pro account(plan_id 2) should be
  # saved with a Stripe subscription function
  # Otherwise, save the sign up as usual.
  def create
    super do |resource|
      # @user = User.new(configure_permitted_parameters)
      if params[:plan]
        resource.plan_id = params[:plan]
        if resource.plan_id == 2
          resource.save_with_subscription
        else
          resource.save
        end
        //These do not works and returns null
        //@user = User.find_by_email(params[:email])
        //@user = User.find(params[:id]
        //@user = resource
        UserMailer.registration_confirmation(params[:email]).deliver
        flash[:success] = "Please confirm your email address to continue"
        redirect_to root_url
      end
    end
  end
  
  private
    def select_plan
      unless (params[:plan] == '1' || params[:plan] == '2')
        flash[:notice] = "Please select a membership plan to sign up."
        redirect_to root_url
      end
    end
end

User model:

class User < ApplicationRecord
  
  before_create :confirmation_token
  
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
         
  belongs_to :plan
  has_one :profile
  
  attr_accessor :stripe_card_token
  
  # If Pro user passes the validation for email, password etc. then call Stripe
  # and tell Stripe to add a subscription by charging customer's card
  # Stripe then returns a customer token in response 
  # Store the token id as customer id and save the user
  def save_with_subscription
    if valid?
      customer = Stripe::Customer.create(description: email, plan: plan_id, card: stripe_card_token)
      self.stripe_customer_token = customer.id
      save!
    end
  end

  private
    
    def confirmation_token
      if self.confirm_token.blank?
          self.confirm_token = SecureRandom.urlsafe_base64.to_s
      end
    end
  
  def email_activate
    self.email_confirmed = true
    self.confirm_token = nil
    save!(:validate => false)
  end
  
end

Anyone has any idea of sending the email confirmation email from devise controller? Thanks in advance!!!


Solution

  • While using devise we can solve the super do requirements in many ways, like adding an after_create action in the User model to send a confirmation email. But I think this solution is handy is you really need to work in with the super do your action with the devise registration controller. Add the codes after the resource saves.

    class Users::RegistrationsController < Devise::RegistrationsController
    
      def create
        super do |resource|
    
       # Your super codes here
        resource.save
    
        yield resource if block_given?
        if resource.persisted?
    
         # We know that the user has been persisted to the database, so now we can send our mail to the resource(user) now!
         UserMailer.registration_confirmation(resource).deliver
         # .... 
        end
        # ....
        end
       end
     # .....
    end
    

    Make sure no double rendering or multi redirect is implied with the devise