Rails 3: Send welcome e-mail using Devise

10,797

Solution 1

I did it by overriding devise's confirm! method: https://gist.github.com/982181

class User < ActiveRecord::Base
  devise :invitable, :database_authenticatable, :registerable, :recoverable, 
         :rememberable, :confirmable, :validatable, :encryptable

  # ...

  # devise confirm! method overriden
  def confirm!
    welcome_message
    super
  end

  # ...

private

  def welcome_message
    UserMailer.welcome_message(self).deliver
  end

end

Solution 2

I can't use the "approved" answer because I'm not using Devise's :confirmable.

I didn't like the other solutions because you have to use model callbacks, which will always send welcome emails even when you create his account in the console or an admin interface. My app involves the ability to mass-import users from a CSV file. I don't want my app sending a surprise email to all 3000 of them one by one, but I do want users who create their own account to get a welcome email. The solution:

1) Override Devise's Registrations controller:

#registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController

  def create
    super
    UserMailer.welcome(resource).deliver unless resource.invalid?
  end

end

2) Tell Devise you overrode its Registrations controller:

# routes.rb
devise_for :users, controllers: { registrations: "registrations" }

Of course, you can adapt "UserMailer" and "devise_for :users" to match the model name you're using.

Solution 3

This is a great discussion. Overriding the method as benoror suggests will work great. If you think you might want to capture other user events, then as some others have suggested elsewhere an Observer class might be the cleanest approach. This solution is for Rails 3.0.x and 3.1.

To set up an observer, you make the following changes to your application file, adding this observer to any others you might already have.

#config/application.rb
config.active_record.observers = :user_observer

Then create a new file in the models directory:

#app/models/user_observer.rb
class UserObserver < ActiveRecord::Observer 
  def after_create(user)
    Notifier.user_new(user).deliver
  end  
end

If you have a cucumber test that exercises the create user functions, you can add this step to that feature and back it up with a worker step to check for an email in the test mail array.

#features/users/sign_up.feature for example
Scenario: User signs up with valid data
  ...
  And I should receive an email with "[Text from your welcome message]"


#features/common_steps.rb
Then /^I should receive an email with "([^"]*)"$/ do |value|
  # this will get the most recent email, so we can check the email headers and body.
  ActionMailer::Base.deliveries.should_not be_empty
  @email = ActionMailer::Base.deliveries.last
  @email.body.should include(value)
  #@email.from.should == ["[email protected]"]
end

You environments/test.rb should have these settings to build a mail array instead of sending:

config.action_mailer.delivery_method = :test
config.action_mailer.perform_deliveries = true

Needless to say you can test for much more (to, from, etc) in the message, but this will get your started in a BDD manner if you are so inclined.

See also some older StackOverflow threads with insight into this question include:

Solution 4

Look into your config/devise.rb

You can change the subjects in your locale files (config/locales/devise.en.yml)

Share:
10,797
donald
Author by

donald

Updated on June 25, 2022

Comments

  • donald
    donald almost 2 years

    How can I send a welcome e-mail when a user registers to my service?

    Also, how do I change the e-mails :from and :subject field from Devise?

    Thanks

  • Arcolye
    Arcolye about 11 years
    What if you're not using :confirmable?
  • Shlomi Zadok
    Shlomi Zadok over 10 years
    If it's not :comfirmable, I'd use the same method but call it :after_create
  • indirect
    indirect over 10 years
    For this to work with Devise for non-users, you need to use resource instead: RegistrationsMailer.welcome(resource).deliver if resource.persisted?
  • Yuki Matsukura
    Yuki Matsukura about 10 years
    In this sentence, the mail is sent even if the user registration is uncompleted.
  • Arcolye
    Arcolye about 10 years
    No this is fine as is. The unless @user.invalid? makes sure that it isn't sent unless registration is completed.