Add layout functionality to mailers.

Mailer layouts behaves just like controller layouts, except layout names need to
have '_mailer' postfix for them to be automatically picked up.
This commit is contained in:
Pratik Naik 2008-08-31 19:11:15 +01:00
parent 7ce03db778
commit e9a8e0053b
9 changed files with 115 additions and 3 deletions

View File

@ -1,3 +1,8 @@
* Add layout functionality to mailers [Pratik]
Mailer layouts behaves just like controller layouts, except layout names need to
have '_mailer' postfix for them to be automatically picked up.
*2.1.0 (May 31st, 2008)*
* Fixed that a return-path header would be ignored #7572 [joost]

View File

@ -246,7 +246,10 @@ module ActionMailer #:nodoc:
# +implicit_parts_order+.
class Base
include AdvAttrAccessor, PartContainer
include ActionController::UrlWriter if Object.const_defined?(:ActionController)
if Object.const_defined?(:ActionController)
include ActionController::UrlWriter
include ActionController::Layout
end
private_class_method :new #:nodoc:
@ -362,6 +365,7 @@ module ActionMailer #:nodoc:
# The mail object instance referenced by this mailer.
attr_reader :mail
attr_reader :template_name, :default_template_name, :action_name
class << self
attr_writer :mailer_name
@ -530,6 +534,7 @@ module ActionMailer #:nodoc:
@content_type ||= @@default_content_type.dup
@implicit_parts_order ||= @@default_implicit_parts_order.dup
@template ||= method_name
@default_template_name = @action_name = @template
@mailer_name ||= self.class.name.underscore
@parts ||= []
@headers ||= {}
@ -546,7 +551,22 @@ module ActionMailer #:nodoc:
if opts[:file] && (opts[:file] !~ /\// && !opts[:file].respond_to?(:render))
opts[:file] = "#{mailer_name}/#{opts[:file]}"
end
initialize_template_class(body).render(opts)
begin
old_template, @template = @template, initialize_template_class(body)
layout = respond_to?(:pick_layout, true) ? pick_layout(opts) : false
@template.render(opts.merge(:layout => layout))
ensure
@template = old_template
end
end
def default_template_format
:html
end
def candidate_for_layout?(options)
!@template.send(:_exempt_from_layout?, default_template_name)
end
def template_root

View File

@ -0,0 +1 @@
Inside

View File

@ -0,0 +1 @@
You logged out

View File

@ -0,0 +1 @@
We do not spam

View File

@ -0,0 +1 @@
Hello from layout <%= yield %>

View File

@ -0,0 +1 @@
Spammer layout <%= yield %>

View File

@ -0,0 +1,78 @@
require 'abstract_unit'
class AutoLayoutMailer < ActionMailer::Base
def hello(recipient)
recipients recipient
subject "You have a mail"
from "tester@example.com"
end
def spam(recipient)
recipients recipient
subject "You have a mail"
from "tester@example.com"
body render(:inline => "Hello, <%= @world %>", :layout => 'spam', :body => { :world => "Earth" })
end
def nolayout(recipient)
recipients recipient
subject "You have a mail"
from "tester@example.com"
body render(:inline => "Hello, <%= @world %>", :layout => false, :body => { :world => "Earth" })
end
end
class ExplicitLayoutMailer < ActionMailer::Base
layout 'spam', :except => [:logout]
def signup(recipient)
recipients recipient
subject "You have a mail"
from "tester@example.com"
end
def logout(recipient)
recipients recipient
subject "You have a mail"
from "tester@example.com"
end
end
class LayoutMailerTest < Test::Unit::TestCase
def setup
set_delivery_method :test
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.deliveries = []
@recipient = 'test@localhost'
end
def teardown
restore_delivery_method
end
def test_should_pickup_default_layout
mail = AutoLayoutMailer.create_hello(@recipient)
assert_equal "Hello from layout Inside", mail.body.strip
end
def test_should_pickup_layout_given_to_render
mail = AutoLayoutMailer.create_spam(@recipient)
assert_equal "Spammer layout Hello, Earth", mail.body.strip
end
def test_should_respect_layout_false
mail = AutoLayoutMailer.create_nolayout(@recipient)
assert_equal "Hello, Earth", mail.body.strip
end
def test_explicit_class_layout
mail = ExplicitLayoutMailer.create_signup(@recipient)
assert_equal "Spammer layout We do not spam", mail.body.strip
end
def test_explicit_layout_exceptions
mail = ExplicitLayoutMailer.create_logout(@recipient)
assert_equal "You logged out", mail.body.strip
end
end

View File

@ -216,7 +216,7 @@ module ActionController #:nodoc:
# object). If the layout was defined without a directory, layouts is assumed. So <tt>layout "weblog/standard"</tt> will return
# weblog/standard, but <tt>layout "standard"</tt> will return layouts/standard.
def active_layout(passed_layout = nil)
layout = passed_layout || self.class.default_layout(response.template.template_format)
layout = passed_layout || self.class.default_layout(default_template_format)
active_layout = case layout
when String then layout
when Symbol then send!(layout)
@ -276,5 +276,9 @@ module ActionController #:nodoc:
rescue ActionView::MissingTemplate
false
end
def default_template_format
response.template.template_format
end
end
end