提交 a381820f 编写于 作者: R Rafael Mendonça França

Merge pull request #17758 from tgxworld/mailer_generator

Follow up to #17646.
* MailerGenerator now generates layouts by default. HTML mailer layout will
include `<html>` and `<body>` tags which will help to reduce spam score in
some spam detection engines. Mailers will now inherit from `ApplicationMailer`
which sets the default layout.
*Andy Jeffries*
* `link_to` and `url_for` generate URLs by default in templates, it is no
longer needed to pass `only_path: false`.
......
......@@ -15,11 +15,17 @@ module ActionMailer
#
# $ rails generate mailer Notifier
#
# The generated model inherits from <tt>ActionMailer::Base</tt>. A mailer model defines methods
# The generated model inherits from <tt>ApplicationMailer</tt> which in turn
# inherits from <tt>ActionMailer::Base</tt>. A mailer model defines methods
# used to generate an email message. In these methods, you can setup variables to be used in
# the mailer views, options on the mail itself such as the <tt>:from</tt> address, and attachments.
#
# class Notifier < ActionMailer::Base
# class ApplicationMailer < ActionMailer::Base
# default from: 'from@exmaple.com'
# layout 'mailer'
# end
#
# class Notifier < ApplicationMailer
# default from: 'no-reply@example.com',
# return_path: 'system@example.com'
#
......@@ -178,7 +184,7 @@ module ActionMailer
#
# Sending attachment in emails is easy:
#
# class ApplicationMailer < ActionMailer::Base
# class Notifier < ApplicationMailer
# def welcome(recipient)
# attachments['free_book.pdf'] = File.read('path/to/file.pdf')
# mail(to: recipient, subject: "New account information")
......@@ -194,7 +200,7 @@ module ActionMailer
# If you need to send attachments with no content, you need to create an empty view for it,
# or add an empty body parameter like this:
#
# class ApplicationMailer < ActionMailer::Base
# class Notifier < ApplicationMailer
# def welcome(recipient)
# attachments['free_book.pdf'] = File.read('path/to/file.pdf')
# mail(to: recipient, subject: "New account information", body: "")
......@@ -206,7 +212,7 @@ module ActionMailer
# You can also specify that a file should be displayed inline with other HTML. This is useful
# if you want to display a corporate logo or a photo.
#
# class ApplicationMailer < ActionMailer::Base
# class Notifier < ApplicationMailer
# def welcome(recipient)
# attachments.inline['photo.png'] = File.read('path/to/photo.png')
# mail(to: recipient, subject: "Here is what we look like")
......@@ -245,7 +251,7 @@ module ActionMailer
# Action Mailer provides some intelligent defaults for your emails, these are usually specified in a
# default method inside the class definition:
#
# class Notifier < ActionMailer::Base
# class Notifier < ApplicationMailer
# default sender: 'system@example.com'
# end
#
......@@ -263,7 +269,7 @@ module ActionMailer
# As you can pass in any header, you need to either quote the header as a string, or pass it in as
# an underscored symbol, so the following will work:
#
# class Notifier < ActionMailer::Base
# class Notifier < ApplicationMailer
# default 'Content-Transfer-Encoding' => '7bit',
# content_description: 'This is a description'
# end
......@@ -271,7 +277,7 @@ module ActionMailer
# Finally, Action Mailer also supports passing <tt>Proc</tt> objects into the default hash, so you
# can define methods that evaluate as the message is being generated:
#
# class Notifier < ActionMailer::Base
# class Notifier < ApplicationMailer
# default 'X-Special-Header' => Proc.new { my_method }
#
# private
......@@ -296,7 +302,7 @@ module ActionMailer
# This may be useful, for example, when you want to add default inline attachments for all
# messages sent out by a certain mailer class:
#
# class Notifier < ActionMailer::Base
# class Notifier < ApplicationMailer
# before_action :add_inline_attachment!
#
# def welcome
......
......@@ -35,10 +35,26 @@ views.
```bash
$ bin/rails generate mailer UserMailer
create app/mailers/user_mailer.rb
create app/mailers/application_mailer.rb
invoke erb
create app/views/user_mailer
create app/views/layouts/mailer.text.erb
create app/views/layouts/mailer.html.erb
invoke test_unit
create test/mailers/user_mailer_test.rb
create test/mailers/previews/user_mailer_preview.rb
```
```ruby
# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
default "from@example.com"
layout 'mailer'
end
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
end
```
As you can see, you can generate mailers just like you use other generators with
......@@ -63,8 +79,7 @@ delivered via email.
`app/mailers/user_mailer.rb` contains an empty mailer:
```ruby
class UserMailer < ActionMailer::Base
default from: 'from@example.com'
class UserMailer < ApplicationMailer
end
```
......@@ -72,7 +87,7 @@ Let's add a method called `welcome_email`, that will send an email to the user's
registered email address:
```ruby
class UserMailer < ActionMailer::Base
class UserMailer < ApplicationMailer
default from: 'notifications@example.com'
def welcome_email(user)
......@@ -348,7 +363,7 @@ for the HTML version and `welcome_email.text.erb` for the plain text version.
To change the default mailer view for your action you do something like:
```ruby
class UserMailer < ActionMailer::Base
class UserMailer < ApplicationMailer
default from: 'notifications@example.com'
def welcome_email(user)
......@@ -370,7 +385,7 @@ If you want more flexibility you can also pass a block and render specific
templates or even render inline or text without using a template file:
```ruby
class UserMailer < ActionMailer::Base
class UserMailer < ApplicationMailer
default from: 'notifications@example.com'
def welcome_email(user)
......@@ -400,7 +415,7 @@ layout.
In order to use a different file, call `layout` in your mailer:
```ruby
class UserMailer < ActionMailer::Base
class UserMailer < ApplicationMailer
layout 'awesome' # use awesome.(html|text).erb as the layout
end
```
......@@ -412,7 +427,7 @@ You can also pass in a `layout: 'layout_name'` option to the render call inside
the format block to specify different layouts for different formats:
```ruby
class UserMailer < ActionMailer::Base
class UserMailer < ApplicationMailer
def welcome_email(user)
mail(to: user.email) do |format|
format.html { render layout: 'my_layout' }
......@@ -510,7 +525,7 @@ while delivering emails, you can do this using `delivery_method_options` in the
mailer action.
```ruby
class UserMailer < ActionMailer::Base
class UserMailer < ApplicationMailer
def welcome_email(user, company)
@user = user
@url = user_url(@user)
......@@ -532,7 +547,7 @@ option. In such cases don't forget to add the `:content_type` option. Rails
will default to `text/plain` otherwise.
```ruby
class UserMailer < ActionMailer::Base
class UserMailer < ApplicationMailer
def welcome_email(user, email_body)
mail(to: user.email,
body: email_body,
......@@ -562,7 +577,7 @@ mailer, and pass the email object to the mailer `receive` instance
method. Here's an example:
```ruby
class UserMailer < ActionMailer::Base
class UserMailer < ApplicationMailer
def receive(email)
page = Page.find_by(address: email.to.first)
page.emails.create(
......@@ -598,7 +613,7 @@ Action Mailer allows for you to specify a `before_action`, `after_action` and
using instance variables set in your mailer action.
```ruby
class UserMailer < ActionMailer::Base
class UserMailer < ApplicationMailer
after_action :set_delivery_options,
:prevent_delivery_to_guests,
:set_business_headers
......
require 'rails/generators/erb/controller/controller_generator'
require 'rails/generators/erb'
module Erb # :nodoc:
module Generators # :nodoc:
class MailerGenerator < ControllerGenerator # :nodoc:
class MailerGenerator < Base # :nodoc:
argument :actions, type: :array, default: [], banner: "method method"
def copy_view_files
view_base_path = File.join("app/views", class_path, file_name)
empty_directory view_base_path
layout_base_path = "app/views/layouts"
formats.each do |format|
layout_path = File.join("app/views/layouts", filename_with_extensions("mailer", format))
template filename_with_extensions(:layout, format), layout_path
end
actions.each do |action|
@action = action
formats.each do |format|
@view_path = File.join(view_base_path, filename_with_extensions(action, format))
template filename_with_extensions(:view, format), @view_path
@layout_path = File.join(layout_base_path, filename_with_extensions("mailer", format))
template filename_with_extensions(:layout, format), @layout_path
@path = File.join(view_base_path, filename_with_extensions(action, format))
template filename_with_extensions(:view, format), @path
end
end
end
protected
......
......@@ -79,10 +79,12 @@ def test_check_preview_class_collision
def test_invokes_default_text_template_engine
run_generator
assert_file "app/views/notifier/foo.text.erb" do |view|
assert_match(%r(\sapp/views/notifier/foo\.text\.erb), view)
assert_match(/<%= @greeting %>/, view)
end
assert_file "app/views/notifier/bar.text.erb" do |view|
assert_match(%r(\sapp/views/notifier/bar\.text\.erb), view)
assert_match(/<%= @greeting %>/, view)
end
......@@ -94,10 +96,12 @@ def test_invokes_default_text_template_engine
def test_invokes_default_html_template_engine
run_generator
assert_file "app/views/notifier/foo.html.erb" do |view|
assert_match(%r(\sapp/views/notifier/foo\.html\.erb), view)
assert_match(/<%= @greeting %>/, view)
end
assert_file "app/views/notifier/bar.html.erb" do |view|
assert_match(%r(\sapp/views/notifier/bar\.html\.erb), view)
assert_match(/<%= @greeting %>/, view)
end
......@@ -109,6 +113,8 @@ def test_invokes_default_html_template_engine
def test_invokes_default_template_engine_even_with_no_action
run_generator ["notifier"]
assert_file "app/views/notifier"
assert_file "app/views/layouts/mailer.text.erb"
assert_file "app/views/layouts/mailer.html.erb"
end
def test_logs_if_the_template_engine_cannot_be_found
......
......@@ -174,10 +174,12 @@ def test_invokes_default_test_framework
def test_invokes_default_template_engine
run_generator
assert_file "app/views/test_app/notifier/foo.text.erb" do |view|
assert_match(%r(app/views/test_app/notifier/foo\.text\.erb), view)
assert_match(/<%= @greeting %>/, view)
end
assert_file "app/views/test_app/notifier/bar.text.erb" do |view|
assert_match(%r(app/views/test_app/notifier/bar\.text\.erb), view)
assert_match(/<%= @greeting %>/, view)
end
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册