Reputation: 45
I'm trying to create a mailer that sends out an email whenever a user signs up. Pretty simple but I'm new to rails.
I have a site that already creates the user. I have a login and sign up page that works correctly, but need some help creating a mailer that sends out an email confirmation link and possibly an option to send out these emails without the user signing up like make a separate page for user invitations.
I've generated a model invitation.rb
class Invitation < ActiveRecord::Base
belongs_to :sender, :class_name => 'User'
has_one :recipient, :class_name => 'User'
validates_presence_of :recipient_email
validate :recipient_is_not_registered
validate :sender_has_invitations, :if => :sender
before_create :generate_token
before_create :decrement_sender_count, :if => :sender
private
def recipient_is_not_registered
errors.add :recipient_email, 'is already registered' if User.find_by_email(recipient_email)
end
def sender_has_invitations
unless sender.invitation_limit > 0
errors.add_to_base 'You have reached your limit of invitations to send.'
end
end
def generate_token
self.token = Digest::SHA1.hexdigest([Time.now, rand].join)
end
def decrement_sender_count
sender.decrement! :invitation_limit
end
#attr_accessible :sender_id, :recipient_email, :token, :sent_at
end
and my invitiation_controller.rb
class InvitationsController < ApplicationController
def new
@invitation = Invitation.new
end
def create
@invitation = Invitation.new(params[:invitation])
@invitation.sender = current_user
if @invitation.save
if logged_in?
Mailer.deliver_invitation(@invitation, signup_url(@invitation.token))
flash[:notice] = "Thank you, invitation sent."
redirect_to projects_url
else
flash[:notice] = "Thank you, we will notify when we are ready."
redirect_to root_url
end
else
render :action => 'new'
end
end
end
What else do I need to edit? how do I hook this up to an already existing user signup and login that is working fine?
Upvotes: 4
Views: 6386
Reputation: 2601
You should already have a UsersController or something like that for registration purposes, which you currently access through the signup_url named route. Suppose that this route is now something like:
http://localhost:3000/register/code_here
All you have to do now is check for the invitation in the controller action and process it accordingly like so:
def new
invite = Invite.find_by_token(params[:id]
if invite.nil?
redirect_to root_path, :notice => "Sorry, you need an invite to register"
end
@user = User.new(:email => invite.recipient_email)
end
def create
invite = Invite.find_by_token(params[:token]
if invite.nil?
redirect_to root_path, :notice => "Sorry, you need an invite to register"
end
begin
invite.nil.transaction do
invite.nil.destroy!
@user = User.create(params[:user)
end
redirect_to my_dashboard_path, :notice => "Yay!"
rescue ActiveRecord::RecordInvalid => invalid
render :new, :alert => "Validation errors"
end
end
Without the invite code, you will simply redirect to root page. You may want to DRY that check though. When someone uses the invite code, you may want to delete it from the database. I wrapped it up in a transaction, but this is up to you (creating the user may be more important).
If you want to create a page that allows users to create invitations without signing up, then simply don't add authentication to InvitationsController and update this snippet:
def create
@invitation = Invitation.new(params[:invitation])
@invitation.sender = current_user if logged_in?
if @invitation.save
Mailer.deliver_invitation(@invitation, signup_url(@invitation.token))
flash[:notice] = "Thank you, invitation sent."
if logged_in?
redirect_to projects_url
else
redirect_to root_url
end
else
render :action => 'new'
end
end
I'm not sure if I covered all the bases, but I think this should point you in the right direction at least.
Upvotes: 2
Reputation: 770
I can not see where Mailer.deliver_invitation comes from, do you use a gem? would it help if you would create mailer.rb, do you have any error mgs/ stack trace?
Have a look here there are some guides, 5 Action Mailer Configuration http://guides.rubyonrails.org/action_mailer_basics.html
Consider using devise for user authentication, https://github.com/plataformatec/devise It is complex, but well documented and easy to configure to jump start.
I assume you are using Rails 3.1 (works also in earlier versions, just find the right guide to your Rails version, to be sure)
Upvotes: 1