From b2504f8ba0f9baadb9298647fd58ef2c136f9aae Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 6 Aug 2008 20:08:27 -0500 Subject: Tidy up ActionMailer rendering logic to take advantage of view path cache instead of using file system lookups --- actionmailer/lib/action_mailer/base.rb | 49 +++++++++++++++------------------- actionmailer/test/mail_service_test.rb | 31 ++++++++------------- 2 files changed, 32 insertions(+), 48 deletions(-) (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index fa29ae2446..1583fb4066 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -216,7 +216,7 @@ module ActionMailer #:nodoc: # * :domain - If you need to specify a HELO domain, you can do it here. # * :user_name - If your mail server requires authentication, set the username in this setting. # * :password - If your mail server requires authentication, set the password in this setting. - # * :authentication - If your mail server requires authentication, you need to specify the authentication type here. + # * :authentication - If your mail server requires authentication, you need to specify the authentication type here. # This is a symbol and one of :plain, :login, :cram_md5. # # * sendmail_settings - Allows you to override options for the :sendmail delivery method. @@ -233,10 +233,10 @@ module ActionMailer #:nodoc: # * deliveries - Keeps an array of all the emails sent out through the Action Mailer with delivery_method :test. Most useful # for unit and functional testing. # - # * default_charset - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also + # * default_charset - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also # pick a different charset from inside a method with +charset+. # * default_content_type - The default content type used for the main part of the message. Defaults to "text/plain". You - # can also pick a different content type from inside a method with +content_type+. + # can also pick a different content type from inside a method with +content_type+. # * default_mime_version - The default mime version used for the message. Defaults to 1.0. You # can also pick a different value from inside a method with +mime_version+. # * default_implicit_parts_order - When a message is built implicitly (i.e. multiple parts are assembled from templates @@ -253,9 +253,6 @@ module ActionMailer #:nodoc: class_inheritable_accessor :view_paths cattr_accessor :logger - cattr_accessor :template_extensions - @@template_extensions = ['erb', 'builder', 'rhtml', 'rxml'] - @@smtp_settings = { :address => "localhost", :port => 25, @@ -414,15 +411,10 @@ module ActionMailer #:nodoc: new.deliver!(mail) end - # Register a template extension so mailer templates written in a - # templating language other than rhtml or rxml are supported. - # To use this, include in your template-language plugin's init - # code or on a per-application basis, this can be invoked from - # config/environment.rb: - # - # ActionMailer::Base.register_template_extension('haml') def register_template_extension(extension) - template_extensions << extension + ActiveSupport::Deprecation.warn( + "ActionMailer::Base.register_template_extension has been deprecated." + + "Use ActionView::Base.register_template_extension instead", caller) end def template_root @@ -455,16 +447,18 @@ module ActionMailer #:nodoc: # "the_template_file.text.html.erb", etc.). Only do this if parts # have not already been specified manually. if @parts.empty? - templates = Dir.glob("#{template_path}/#{@template}.*") - templates.each do |path| - basename = File.basename(path) - template_regex = Regexp.new("^([^\\\.]+)\\\.([^\\\.]+\\\.[^\\\.]+)\\\.(" + template_extensions.join('|') + ")$") - next unless md = template_regex.match(basename) - template_name = basename - content_type = md.captures[1].gsub('.', '/') - @parts << Part.new(:content_type => content_type, - :disposition => "inline", :charset => charset, - :body => render_message(template_name, @body)) + Dir.glob("#{template_path}/#{@template}.*").each do |path| + template = template_root["#{mailer_name}/#{File.basename(path)}"] + + # Skip unless template has a multipart format + next unless template.multipart? + + @parts << Part.new( + :content_type => template.content_type, + :disposition => "inline", + :charset => charset, + :body => render_message(template, @body) + ) end unless @parts.empty? @content_type = "multipart/alternative" @@ -476,9 +470,8 @@ module ActionMailer #:nodoc: # also render a "normal" template (without the content type). If a # normal template exists (or if there were no implicit parts) we render # it. - template_exists = @parts.empty? - template_exists ||= Dir.glob("#{template_path}/#{@template}.*").any? { |i| File.basename(i).split(".").length == 2 } - @body = render_message(@template, @body) if template_exists + template = template_root["#{mailer_name}/#{@template}"] + @body = render_message(@template, @body) if template # Finally, if there are other message parts and a textual body exists, # we shift it onto the front of the parts and set the body to nil (so @@ -538,7 +531,7 @@ module ActionMailer #:nodoc: def render(opts) body = opts.delete(:body) - if opts[:file] && opts[:file] !~ /\// + if opts[:file] && (opts[:file] !~ /\// && !opts[:file].respond_to?(:render)) opts[:file] = "#{mailer_name}/#{opts[:file]}" end initialize_template_class(body).render(opts) diff --git a/actionmailer/test/mail_service_test.rb b/actionmailer/test/mail_service_test.rb index e5ecb0e254..882b07d675 100644 --- a/actionmailer/test/mail_service_test.rb +++ b/actionmailer/test/mail_service_test.rb @@ -219,7 +219,7 @@ class TestMailer < ActionMailer::Base end attachment :content_type => "application/octet-stream",:filename => "test.txt", :body => "test abcdefghijklmnopqstuvwxyz" end - + def nested_multipart_with_body(recipient) recipients recipient subject "nested multipart with body" @@ -321,7 +321,7 @@ class ActionMailerTest < Test::Unit::TestCase assert_nothing_raised { created = TestMailer.create_nested_multipart(@recipient)} assert_equal 2,created.parts.size assert_equal 2,created.parts.first.parts.size - + assert_equal "multipart/mixed", created.content_type assert_equal "multipart/alternative", created.parts.first.content_type assert_equal "bar", created.parts.first.header['foo'].to_s @@ -366,7 +366,7 @@ class ActionMailerTest < Test::Unit::TestCase assert_not_nil ActionMailer::Base.deliveries.first assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded end - + def test_custom_template expected = new_mail expected.to = @recipient @@ -382,7 +382,6 @@ class ActionMailerTest < Test::Unit::TestCase end def test_custom_templating_extension - # # N.b., custom_templating_extension.text.plain.haml is expected to be in fixtures/test_mailer directory expected = new_mail expected.to = @recipient @@ -390,18 +389,10 @@ class ActionMailerTest < Test::Unit::TestCase expected.body = "Hello there, \n\nMr. #{@recipient}" expected.from = "system@loudthinking.com" expected.date = Time.local(2004, 12, 12) - + # Stub the render method so no alternative renderers need be present. ActionView::Base.any_instance.stubs(:render).returns("Hello there, \n\nMr. #{@recipient}") - - # If the template is not registered, there should be no parts. - created = nil - assert_nothing_raised { created = TestMailer.create_custom_templating_extension(@recipient) } - assert_not_nil created - assert_equal 0, created.parts.length - - ActionMailer::Base.register_template_extension('haml') - + # Now that the template is registered, there should be one part. The text/plain part. created = nil assert_nothing_raised { created = TestMailer.create_custom_templating_extension(@recipient) } @@ -428,7 +419,7 @@ class ActionMailerTest < Test::Unit::TestCase assert_not_nil ActionMailer::Base.deliveries.first assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded end - + def test_cc_bcc expected = new_mail expected.to = @recipient @@ -550,7 +541,7 @@ class ActionMailerTest < Test::Unit::TestCase TestMailer.deliver_signed_up(@recipient) assert_equal 1, ActionMailer::Base.deliveries.size end - + def test_doesnt_raise_errors_when_raise_delivery_errors_is_false ActionMailer::Base.raise_delivery_errors = false TestMailer.any_instance.expects(:perform_delivery_test).raises(Exception) @@ -670,7 +661,7 @@ EOF assert_not_nil ActionMailer::Base.deliveries.first assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded end - + def test_utf8_body_is_not_quoted @recipient = "Foo áëô îü " expected = new_mail "utf-8" @@ -760,7 +751,7 @@ EOF mail = TestMailer.create_multipart_with_mime_version(@recipient) assert_equal "1.1", mail.mime_version end - + def test_multipart_with_utf8_subject mail = TestMailer.create_multipart_with_utf8_subject(@recipient) assert_match(/\nSubject: =\?utf-8\?Q\?Foo_.*?\?=/, mail.encoded) @@ -825,7 +816,7 @@ EOF mail = TestMailer.create_implicitly_multipart_example(@recipient, 'iso-8859-1') assert_equal "multipart/alternative", mail.header['content-type'].body - + assert_equal 'iso-8859-1', mail.parts[0].sub_header("content-type", "charset") assert_equal 'iso-8859-1', mail.parts[1].sub_header("content-type", "charset") assert_equal 'iso-8859-1', mail.parts[2].sub_header("content-type", "charset") @@ -852,7 +843,7 @@ EOF assert_equal "line #1\nline #2\nline #3\nline #4\n\n", mail.parts[0].body assert_equal "

line #1

\n

line #2

\n

line #3

\n

line #4

\n\n", mail.parts[1].body end - + def test_headers_removed_on_smtp_delivery ActionMailer::Base.delivery_method = :smtp TestMailer.deliver_cc_bcc(@recipient) -- cgit v1.2.3 From 04248c62086b188ae354ed90ae40c832b79fd19c Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Wed, 13 Aug 2008 19:04:56 -0500 Subject: Ensure templates are rendered if all the parts are already processed --- actionmailer/lib/action_mailer/base.rb | 5 +++-- actionmailer/test/fixtures/test_mailer/signed_up.erb | 3 --- actionmailer/test/fixtures/test_mailer/signed_up.html.erb | 3 +++ 3 files changed, 6 insertions(+), 5 deletions(-) delete mode 100644 actionmailer/test/fixtures/test_mailer/signed_up.erb create mode 100644 actionmailer/test/fixtures/test_mailer/signed_up.html.erb (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 1583fb4066..72c94529b5 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -470,8 +470,9 @@ module ActionMailer #:nodoc: # also render a "normal" template (without the content type). If a # normal template exists (or if there were no implicit parts) we render # it. - template = template_root["#{mailer_name}/#{@template}"] - @body = render_message(@template, @body) if template + template_exists = @parts.empty? + template_exists ||= template_root["#{mailer_name}/#{@template}"] + @body = render_message(@template, @body) if template_exists # Finally, if there are other message parts and a textual body exists, # we shift it onto the front of the parts and set the body to nil (so diff --git a/actionmailer/test/fixtures/test_mailer/signed_up.erb b/actionmailer/test/fixtures/test_mailer/signed_up.erb deleted file mode 100644 index a85d5fa442..0000000000 --- a/actionmailer/test/fixtures/test_mailer/signed_up.erb +++ /dev/null @@ -1,3 +0,0 @@ -Hello there, - -Mr. <%= @recipient %> \ No newline at end of file diff --git a/actionmailer/test/fixtures/test_mailer/signed_up.html.erb b/actionmailer/test/fixtures/test_mailer/signed_up.html.erb new file mode 100644 index 0000000000..a85d5fa442 --- /dev/null +++ b/actionmailer/test/fixtures/test_mailer/signed_up.html.erb @@ -0,0 +1,3 @@ +Hello there, + +Mr. <%= @recipient %> \ No newline at end of file -- cgit v1.2.3