Mailer subjects namespaced by model

This commit is contained in:
Carlos A. da Silva 2009-10-20 01:28:01 -02:00
parent d26f90f72b
commit 0eb8b3b7cc
7 changed files with 123 additions and 36 deletions

View File

@ -7,7 +7,7 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
* Allows you to have multiple roles (or models/scopes) signed in at the same time;
* Is based on a modularity concept: use just what you really need.
Right now it's composed of four mainly modules:
Right now it's composed of five mainly modules:
* Authenticable: responsible for encrypting password and validating authenticity of a user while signing in.
* Confirmable: responsible for verifying whether an account is already confirmed to sign in, and to send emails with confirmation instructions.
@ -170,6 +170,37 @@ Devise let's you setup as many roles as you want, so let's say you already have
current_admin
admin_session
== I18n
Devise check for flash messages using i18n, so you're able to customize them easily. For example, to change the sign in message you should setup your locale file this way:
en:
devise:
sessions:
signed_in: 'Signed in successfully.'
You can also create distinct messages based on the resource you've configured:
en:
devise:
sessions:
user:
signed_in: 'Welcome user, you are signed in.'
admin:
signed_in: 'Hello admin!'
Devise notifier uses the same pattern to create subject messages, but it is not able to know what scope you are, he just know the record (ie user instance) that was sent to it. So you need to customize messages based on the model class name (usually the same as the resource name, if you follow basic conventions):
en:
devise:
notifier:
confirmation_instructions: 'Hello everybody!'
user:
confirmation_instructions: 'Hello User! Please confirm your email'
reset_password_instructions: 'Reset instructions'
Take a look at our locale file to check all available messages.
== TODO
Please refer to TODO file.

2
TODO
View File

@ -2,7 +2,6 @@
* Create generators
* Allow stretches and pepper per model
* Mailer subjects namespaced by model
* Use request_ip in session cookies
* Session timeout
@ -34,3 +33,4 @@
* Sign user in automatically after confirming or changing it's password
* Add remember me
* Mailer subjects namespaced by model

View File

@ -4,20 +4,19 @@ class Notifier < ::ActionMailer::Base
# Deliver confirmation instructions when the user is created or its email is
# updated, and also when confirmation is manually requested
def confirmation_instructions(record)
subject translate(:confirmation_instructions, :default => 'Confirmation instructions')
setup_mail(record)
setup_mail(record, :confirmation_instructions)
end
# Deliver reset password instructions when manually requested
def reset_password_instructions(record)
subject translate(:reset_password_instructions, :default => 'Reset password instructions')
setup_mail(record)
setup_mail(record, :reset_password_instructions)
end
private
# Configure default email options
def setup_mail(record)
def setup_mail(record, key)
subject translate(record, key)
from self.class.sender
recipients record.email
sent_on Time.now
@ -25,7 +24,20 @@ class Notifier < ::ActionMailer::Base
body record.class.name.downcase.to_sym => record, :resource => record
end
def translate(key, options={})
I18n.t(key, {:scope => [:devise, :notifier]}.merge(options))
# Setup subject namespaced by model. It means you're able to setup your
# messages using specific resource scope, or provide a default one.
# Example (i18n locale file):
#
# en:
# devise:
# notifier:
# confirmation_instructions: '...'
# user:
# notifier:
# confirmation_instructions: '...'
def translate(record, key)
I18n.t(:"#{record.class.name.downcase}.#{key}",
:scope => [:devise, :notifier],
:default => key)
end
end

View File

@ -76,8 +76,7 @@ module Devise
# devise:
# passwords:
# #default_scope_messages - only if resource_scope is not found
# user:
# passwords:
# user:
# #resource_scope_messages
#
# Please refer to README or en.yml locale file to check what messages are

View File

@ -1,42 +1,59 @@
require 'test_helper'
require 'test/test_helper'
class ConfirmationInstructionsTest < ActionMailer::TestCase
def setup
setup_mailer
I18n.backend.store_translations :en, {:devise => { :notifier => { :confirmation_instructions => 'Account Confirmation' } }}
Notifier.sender = 'test@example.com'
@user = create_user
@mail = ActionMailer::Base.deliveries.first
end
def user
@user ||= create_user
end
def mail
@mail ||= begin
user
ActionMailer::Base.deliveries.first
end
end
test 'email sent after creating the user' do
assert_not_nil @mail
assert_not_nil mail
end
test 'content type should be set to html' do
assert_equal 'text/html', @mail.content_type
assert_equal 'text/html', mail.content_type
end
test 'send confirmation instructions to the user email' do
assert_equal [@user.email], @mail.to
mail
assert_equal [user.email], mail.to
end
test 'setup sender from configuration' do
assert_equal ['test@example.com'], @mail.from
assert_equal ['test@example.com'], mail.from
end
test 'setup subject from I18n' do
assert_equal 'Account Confirmation', @mail.subject
store_translations :en, :devise => { :notifier => { :confirmation_instructions => 'Account Confirmation' } } do
assert_equal 'Account Confirmation', mail.subject
end
end
test 'subject namespaced by model' do
store_translations :en, :devise => { :notifier => { :user => { :confirmation_instructions => 'User Account Confirmation' } } } do
assert_equal 'User Account Confirmation', mail.subject
end
end
test 'body should have user info' do
assert_match /#{@user.email}/, @mail.body
assert_match /#{user.email}/, mail.body
end
test 'body should have link to confirm the account' do
host = ActionMailer::Base.default_url_options[:host]
confirmation_url_regexp = %r{<a href=\"http://#{host}/users/confirmation\?confirmation_token=#{@user.confirmation_token}">}
assert_match confirmation_url_regexp, @mail.body
confirmation_url_regexp = %r{<a href=\"http://#{host}/users/confirmation\?confirmation_token=#{user.confirmation_token}">}
assert_match confirmation_url_regexp, mail.body
end
end

View File

@ -1,43 +1,62 @@
require 'test_helper'
require 'test/test_helper'
class ResetPasswordInstructionsTest < ActionMailer::TestCase
def setup
setup_mailer
I18n.backend.store_translations :en, {:devise => { :notifier => { :reset_password_instructions => 'Reset instructions' } }}
Notifier.sender = 'test@example.com'
@user = create_user
@user.send_reset_password_instructions
@mail = ActionMailer::Base.deliveries.last
end
def user
@user ||= begin
user = create_user
user.send_reset_password_instructions
user
end
end
def mail
@mail ||= begin
user
ActionMailer::Base.deliveries.last
end
end
test 'email sent after reseting the user password' do
assert_not_nil @mail
assert_not_nil mail
end
test 'content type should be set to html' do
assert_equal 'text/html', @mail.content_type
assert_equal 'text/html', mail.content_type
end
test 'send confirmation instructions to the user email' do
assert_equal [@user.email], @mail.to
assert_equal [user.email], mail.to
end
test 'setup sender from configuration' do
assert_equal ['test@example.com'], @mail.from
assert_equal ['test@example.com'], mail.from
end
test 'setup subject from I18n' do
assert_equal 'Reset instructions', @mail.subject
store_translations :en, :devise => { :notifier => { :reset_password_instructions => 'Reset instructions' } } do
assert_equal 'Reset instructions', mail.subject
end
end
test 'subject namespaced by model' do
store_translations :en, :devise => { :notifier => { :user => { :reset_password_instructions => 'User Reset Instructions' } } } do
assert_equal 'User Reset Instructions', mail.subject
end
end
test 'body should have user info' do
assert_match /#{@user.email}/, @mail.body
assert_match /#{user.email}/, mail.body
end
test 'body should have link to confirm the account' do
host = ActionMailer::Base.default_url_options[:host]
confirmation_url_regexp = %r{<a href=\"http://#{host}/users/password/edit\?reset_password_token=#{@user.reset_password_token}">}
assert_match confirmation_url_regexp, @mail.body
reset_url_regexp = %r{<a href=\"http://#{host}/users/password/edit\?reset_password_token=#{user.reset_password_token}">}
assert_match reset_url_regexp, mail.body
end
end

View File

@ -3,6 +3,15 @@ class ActiveSupport::TestCase
ActionMailer::Base.deliveries = []
end
def store_translations(locale, translations, &block)
begin
I18n.backend.store_translations locale, translations
yield
ensure
I18n.reload!
end
end
# Helpers for creating new users
#
def generate_unique_email