Skip to content
This repository
Browse code

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.
  • Loading branch information...
commit e9a8e0053be3b293ab89fb584f1d660063f107aa 1 parent 7ce03db
Pratik authored
5  actionmailer/CHANGELOG
... ...
@@ -1,3 +1,8 @@
  1
+* Add layout functionality to mailers [Pratik]
  2
+
  3
+  Mailer layouts behaves just like controller layouts, except layout names need to
  4
+  have '_mailer' postfix for them to be automatically picked up.
  5
+
1 6
 *2.1.0 (May 31st, 2008)*
2 7
 
3 8
 * Fixed that a return-path header would be ignored #7572 [joost]
24  actionmailer/lib/action_mailer/base.rb
@@ -246,7 +246,10 @@ module ActionMailer #:nodoc:
246 246
   #   +implicit_parts_order+.
247 247
   class Base
248 248
     include AdvAttrAccessor, PartContainer
249  
-    include ActionController::UrlWriter if Object.const_defined?(:ActionController)
  249
+    if Object.const_defined?(:ActionController)
  250
+      include ActionController::UrlWriter
  251
+      include ActionController::Layout
  252
+    end
250 253
 
251 254
     private_class_method :new #:nodoc:
252 255
 
@@ -362,6 +365,7 @@ def mailer_name=(value)
362 365
 
363 366
     # The mail object instance referenced by this mailer.
364 367
     attr_reader :mail
  368
+    attr_reader :template_name, :default_template_name, :action_name
365 369
 
366 370
     class << self
367 371
       attr_writer :mailer_name
@@ -530,6 +534,7 @@ def initialize_defaults(method_name)
530 534
         @content_type ||= @@default_content_type.dup
531 535
         @implicit_parts_order ||= @@default_implicit_parts_order.dup
532 536
         @template ||= method_name
  537
+        @default_template_name = @action_name = @template
533 538
         @mailer_name ||= self.class.name.underscore
534 539
         @parts ||= []
535 540
         @headers ||= {}
@@ -546,7 +551,22 @@ def render(opts)
546 551
         if opts[:file] && (opts[:file] !~ /\// && !opts[:file].respond_to?(:render))
547 552
           opts[:file] = "#{mailer_name}/#{opts[:file]}"
548 553
         end
549  
-        initialize_template_class(body).render(opts)
  554
+
  555
+        begin
  556
+          old_template, @template = @template, initialize_template_class(body)
  557
+          layout = respond_to?(:pick_layout, true) ? pick_layout(opts) : false
  558
+          @template.render(opts.merge(:layout => layout))
  559
+        ensure
  560
+          @template = old_template
  561
+        end
  562
+      end
  563
+
  564
+      def default_template_format
  565
+        :html
  566
+      end
  567
+
  568
+      def candidate_for_layout?(options)
  569
+        !@template.send(:_exempt_from_layout?, default_template_name)
550 570
       end
551 571
 
552 572
       def template_root
1  actionmailer/test/fixtures/auto_layout_mailer/hello.html.erb
... ...
@@ -0,0 +1 @@
  1
+Inside
1  actionmailer/test/fixtures/explicit_layout_mailer/logout.html.erb
... ...
@@ -0,0 +1 @@
  1
+You logged out
1  actionmailer/test/fixtures/explicit_layout_mailer/signup.html.erb
... ...
@@ -0,0 +1 @@
  1
+We do not spam
1  actionmailer/test/fixtures/layouts/auto_layout_mailer.html.erb
... ...
@@ -0,0 +1 @@
  1
+Hello from layout <%= yield %>
1  actionmailer/test/fixtures/layouts/spam.html.erb
... ...
@@ -0,0 +1 @@
  1
+Spammer layout <%= yield %>
78  actionmailer/test/mail_layout_test.rb
... ...
@@ -0,0 +1,78 @@
  1
+require 'abstract_unit'
  2
+
  3
+class AutoLayoutMailer < ActionMailer::Base
  4
+  def hello(recipient)
  5
+    recipients recipient
  6
+    subject    "You have a mail"
  7
+    from       "tester@example.com"
  8
+  end
  9
+
  10
+  def spam(recipient)
  11
+    recipients recipient
  12
+    subject    "You have a mail"
  13
+    from       "tester@example.com"
  14
+    body       render(:inline => "Hello, <%= @world %>", :layout => 'spam', :body => { :world => "Earth" })
  15
+  end
  16
+
  17
+  def nolayout(recipient)
  18
+    recipients recipient
  19
+    subject    "You have a mail"
  20
+    from       "tester@example.com"
  21
+    body       render(:inline => "Hello, <%= @world %>", :layout => false, :body => { :world => "Earth" })
  22
+  end
  23
+end
  24
+
  25
+class ExplicitLayoutMailer < ActionMailer::Base
  26
+  layout 'spam', :except => [:logout]
  27
+
  28
+  def signup(recipient)
  29
+    recipients recipient
  30
+    subject    "You have a mail"
  31
+    from       "tester@example.com"
  32
+  end
  33
+
  34
+  def logout(recipient)
  35
+    recipients recipient
  36
+    subject    "You have a mail"
  37
+    from       "tester@example.com"
  38
+  end
  39
+end
  40
+
  41
+class LayoutMailerTest < Test::Unit::TestCase
  42
+  def setup
  43
+    set_delivery_method :test
  44
+    ActionMailer::Base.perform_deliveries = true
  45
+    ActionMailer::Base.deliveries = []
  46
+
  47
+    @recipient = 'test@localhost'
  48
+  end
  49
+
  50
+  def teardown
  51
+    restore_delivery_method
  52
+  end
  53
+
  54
+  def test_should_pickup_default_layout
  55
+    mail = AutoLayoutMailer.create_hello(@recipient)
  56
+    assert_equal "Hello from layout Inside", mail.body.strip
  57
+  end
  58
+
  59
+  def test_should_pickup_layout_given_to_render
  60
+    mail = AutoLayoutMailer.create_spam(@recipient)
  61
+    assert_equal "Spammer layout Hello, Earth", mail.body.strip
  62
+  end
  63
+
  64
+  def test_should_respect_layout_false
  65
+    mail = AutoLayoutMailer.create_nolayout(@recipient)
  66
+    assert_equal "Hello, Earth", mail.body.strip
  67
+  end
  68
+
  69
+  def test_explicit_class_layout
  70
+    mail = ExplicitLayoutMailer.create_signup(@recipient)
  71
+    assert_equal "Spammer layout We do not spam", mail.body.strip
  72
+  end
  73
+
  74
+  def test_explicit_layout_exceptions
  75
+    mail = ExplicitLayoutMailer.create_logout(@recipient)
  76
+    assert_equal "You logged out", mail.body.strip
  77
+  end
  78
+end
6  actionpack/lib/action_controller/layout.rb
@@ -216,7 +216,7 @@ def default_layout_with_format(format, layout)
216 216
     # object). If the layout was defined without a directory, layouts is assumed. So <tt>layout "weblog/standard"</tt> will return
217 217
     # weblog/standard, but <tt>layout "standard"</tt> will return layouts/standard.
218 218
     def active_layout(passed_layout = nil)
219  
-      layout = passed_layout || self.class.default_layout(response.template.template_format)
  219
+      layout = passed_layout || self.class.default_layout(default_template_format)
220 220
       active_layout = case layout
221 221
         when String then layout
222 222
         when Symbol then send!(layout)
@@ -276,5 +276,9 @@ def layout_directory?(layout_name)
276 276
       rescue ActionView::MissingTemplate
277 277
         false
278 278
       end
  279
+
  280
+      def default_template_format
  281
+        response.template.template_format
  282
+      end
279 283
   end
280 284
 end

0 notes on commit e9a8e00

Please sign in to comment.
Something went wrong with that request. Please try again.