actionmailer 7.0.8.4 → 7.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionmailer might be problematic. Click here for more details.

@@ -3,13 +3,18 @@
3
3
  require "active_job"
4
4
 
5
5
  module ActionMailer
6
- # The <tt>ActionMailer::MailDeliveryJob</tt> class is used when you
6
+ # = Action Mailer \MailDeliveryJob
7
+ #
8
+ # The +ActionMailer::MailDeliveryJob+ class is used when you
7
9
  # want to send emails outside of the request-response cycle. It supports
8
10
  # sending either parameterized or normal mail.
9
11
  #
10
12
  # Exceptions are rescued and handled by the mailer class.
11
13
  class MailDeliveryJob < ActiveJob::Base # :nodoc:
12
- queue_as { ActionMailer::Base.deliver_later_queue_name }
14
+ queue_as do
15
+ mailer_class = arguments.first.constantize
16
+ mailer_class.deliver_later_queue_name
17
+ end
13
18
 
14
19
  rescue_from StandardError, with: :handle_exception_with_mailer_class
15
20
 
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionMailer
4
+ # = Action Mailer \MailHelper
5
+ #
4
6
  # Provides helper methods for ActionMailer::Base that can be used for easily
5
7
  # formatting messages, accessing mailer or message instances, and the
6
8
  # attachments list.
@@ -3,11 +3,13 @@
3
3
  require "delegate"
4
4
 
5
5
  module ActionMailer
6
- # The <tt>ActionMailer::MessageDelivery</tt> class is used by
6
+ # = Action Mailer \MessageDelivery
7
+ #
8
+ # The +ActionMailer::MessageDelivery+ class is used by
7
9
  # ActionMailer::Base when creating a new mailer.
8
10
  # <tt>MessageDelivery</tt> is a wrapper (+Delegator+ subclass) around a lazy
9
- # created <tt>Mail::Message</tt>. You can get direct access to the
10
- # <tt>Mail::Message</tt>, deliver the email or schedule the email to be sent
11
+ # created +Mail::Message+. You can get direct access to the
12
+ # +Mail::Message+, deliver the email or schedule the email to be sent
11
13
  # through Active Job.
12
14
  #
13
15
  # Notifier.welcome(User.first) # an ActionMailer::MessageDelivery object
@@ -62,9 +64,10 @@ module ActionMailer
62
64
  # * <tt>:queue</tt> - Enqueue the email on the specified queue
63
65
  # * <tt>:priority</tt> - Enqueues the email with the specified priority
64
66
  #
65
- # By default, the email will be enqueued using <tt>ActionMailer::MailDeliveryJob</tt>. Each
66
- # ActionMailer::Base class can specify the job to use by setting the class variable
67
- # +delivery_job+.
67
+ # By default, the email will be enqueued using ActionMailer::MailDeliveryJob on
68
+ # the default queue. Mailer classes can customize the queue name used for the default
69
+ # job by assigning a +deliver_later_queue_name+ class variable, or provide a custom job
70
+ # by assigning a +delivery_job+. When a custom job is used, it controls the queue name.
68
71
  #
69
72
  # class AccountRegistrationMailer < ApplicationMailer
70
73
  # self.delivery_job = RegistrationDeliveryJob
@@ -88,9 +91,10 @@ module ActionMailer
88
91
  # * <tt>:queue</tt> - Enqueue the email on the specified queue.
89
92
  # * <tt>:priority</tt> - Enqueues the email with the specified priority
90
93
  #
91
- # By default, the email will be enqueued using <tt>ActionMailer::MailDeliveryJob</tt>. Each
92
- # ActionMailer::Base class can specify the job to use by setting the class variable
93
- # +delivery_job+.
94
+ # By default, the email will be enqueued using ActionMailer::MailDeliveryJob on
95
+ # the default queue. Mailer classes can customize the queue name used for the default
96
+ # job by assigning a +deliver_later_queue_name+ class variable, or provide a custom job
97
+ # by assigning a +delivery_job+. When a custom job is used, it controls the queue name.
94
98
  #
95
99
  # class AccountRegistrationMailer < ApplicationMailer
96
100
  # self.delivery_job = RegistrationDeliveryJob
@@ -106,7 +110,9 @@ module ActionMailer
106
110
  #
107
111
  def deliver_now!
108
112
  processed_mailer.handle_exceptions do
109
- message.deliver!
113
+ processed_mailer.run_callbacks(:deliver) do
114
+ message.deliver!
115
+ end
110
116
  end
111
117
  end
112
118
 
@@ -116,13 +122,15 @@ module ActionMailer
116
122
  #
117
123
  def deliver_now
118
124
  processed_mailer.handle_exceptions do
119
- message.deliver
125
+ processed_mailer.run_callbacks(:deliver) do
126
+ message.deliver
127
+ end
120
128
  end
121
129
  end
122
130
 
123
131
  private
124
132
  # Returns the processed Mailer instance. We keep this instance
125
- # on hand so we can delegate exception handling to it.
133
+ # on hand so we can run callbacks and delegate exception handling to it.
126
134
  def processed_mailer
127
135
  @processed_mailer ||= @mailer_class.new.tap do |mailer|
128
136
  mailer.process @action, *@args
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionMailer
4
+ # = Action Mailer \Parameterized
5
+ #
4
6
  # Provides the option to parameterize mailers in order to share instance variable
5
7
  # setup, processing, and common headers.
6
8
  #
@@ -88,7 +90,11 @@ module ActionMailer
88
90
  extend ActiveSupport::Concern
89
91
 
90
92
  included do
91
- attr_accessor :params
93
+ attr_writer :params
94
+
95
+ def params
96
+ @params ||= {}
97
+ end
92
98
  end
93
99
 
94
100
  module ClassMethods
@@ -7,11 +7,11 @@ module ActionMailer
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
- # Set the location of mailer previews through app configuration:
10
+ # Add the location of mailer previews through app configuration:
11
11
  #
12
- # config.action_mailer.preview_path = "#{Rails.root}/lib/mailer_previews"
12
+ # config.action_mailer.preview_paths << "#{Rails.root}/lib/mailer_previews"
13
13
  #
14
- mattr_accessor :preview_path, instance_writer: false
14
+ mattr_accessor :preview_paths, instance_writer: false, default: []
15
15
 
16
16
  # Enable or disable mailer previews through app configuration:
17
17
  #
@@ -25,7 +25,31 @@ module ActionMailer
25
25
  mattr_accessor :preview_interceptors, instance_writer: false, default: [ActionMailer::InlinePreviewInterceptor]
26
26
  end
27
27
 
28
+ def preview_path
29
+ ActionMailer.deprecator.warn(<<-MSG.squish)
30
+ Using preview_path option is deprecated and will be removed in Rails 7.2.
31
+ Please use preview_paths instead.
32
+ MSG
33
+ self.class.preview_paths.first
34
+ end
35
+
28
36
  module ClassMethods
37
+ def preview_path=(value)
38
+ ActionMailer.deprecator.warn(<<-MSG.squish)
39
+ Using preview_path= option is deprecated and will be removed in Rails 7.2.
40
+ Please use preview_paths= instead.
41
+ MSG
42
+ self.preview_paths << value
43
+ end
44
+
45
+ def preview_path
46
+ ActionMailer.deprecator.warn(<<-MSG.squish)
47
+ Using preview_path option is deprecated and will be removed in Rails 7.2.
48
+ Please use preview_paths instead.
49
+ MSG
50
+ self.preview_paths.first
51
+ end
52
+
29
53
  # Register one or more Interceptors which will be called before mail is previewed.
30
54
  def register_preview_interceptors(*interceptors)
31
55
  interceptors.flatten.compact.each { |interceptor| register_preview_interceptor(interceptor) }
@@ -79,7 +103,7 @@ module ActionMailer
79
103
  # Returns all mailer preview classes.
80
104
  def all
81
105
  load_previews if descendants.empty?
82
- descendants
106
+ descendants.sort_by { |mailer| mailer.name.titleize }
83
107
  end
84
108
 
85
109
  # Returns the mail object for the given email name. The registered preview
@@ -119,13 +143,13 @@ module ActionMailer
119
143
 
120
144
  private
121
145
  def load_previews
122
- if preview_path
123
- Dir["#{preview_path}/**/*_preview.rb"].sort.each { |file| require_dependency file }
146
+ preview_paths.each do |preview_path|
147
+ Dir["#{preview_path}/**/*_preview.rb"].sort.each { |file| require file }
124
148
  end
125
149
  end
126
150
 
127
- def preview_path
128
- Base.preview_path
151
+ def preview_paths
152
+ Base.preview_paths
129
153
  end
130
154
 
131
155
  def show_previews
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionMailer
4
+ module QueuedDelivery
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_attribute :delivery_job, default: ::ActionMailer::MailDeliveryJob
9
+ class_attribute :deliver_later_queue_name, default: :mailers
10
+ end
11
+ end
12
+ end
@@ -8,8 +8,13 @@ require "abstract_controller/railties/routes_helpers"
8
8
  module ActionMailer
9
9
  class Railtie < Rails::Railtie # :nodoc:
10
10
  config.action_mailer = ActiveSupport::OrderedOptions.new
11
+ config.action_mailer.preview_paths = []
11
12
  config.eager_load_namespaces << ActionMailer
12
13
 
14
+ initializer "action_mailer.deprecator", before: :load_environment_config do |app|
15
+ app.deprecators[:action_mailer] = ActionMailer.deprecator
16
+ end
17
+
13
18
  initializer "action_mailer.logger" do
14
19
  ActiveSupport.on_load(:action_mailer) { self.logger ||= Rails.logger }
15
20
  end
@@ -23,10 +28,7 @@ module ActionMailer
23
28
  options.stylesheets_dir ||= paths["public/stylesheets"].first
24
29
  options.show_previews = Rails.env.development? if options.show_previews.nil?
25
30
  options.cache_store ||= Rails.cache
26
-
27
- if options.show_previews
28
- options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/mailers/previews" : nil
29
- end
31
+ options.preview_paths |= ["#{Rails.root}/test/mailers/previews"]
30
32
 
31
33
  # make sure readers methods get compiled
32
34
  options.asset_host ||= app.config.asset_host
@@ -40,6 +42,7 @@ module ActionMailer
40
42
  register_interceptors(options.delete(:interceptors))
41
43
  register_preview_interceptors(options.delete(:preview_interceptors))
42
44
  register_observers(options.delete(:observers))
45
+ self.preview_paths |= options[:preview_paths]
43
46
 
44
47
  if delivery_job = options.delete(:delivery_job)
45
48
  self.delivery_job = delivery_job.constantize
@@ -65,12 +68,19 @@ module ActionMailer
65
68
  end
66
69
  end
67
70
 
68
- initializer "action_mailer.set_autoload_paths" do |app|
71
+ initializer "action_mailer.set_autoload_paths", before: :set_autoload_paths do |app|
69
72
  options = app.config.action_mailer
70
-
71
- if options.show_previews && options.preview_path
72
- ActiveSupport::Dependencies.autoload_paths << options.preview_path
73
- end
73
+ app.config.paths["test/mailers/previews"].concat(options.preview_paths)
74
+
75
+ # Preview paths configuration needs a pass.
76
+ #
77
+ # config.paths is cached as soon as it is accessed. Therefore, mutating
78
+ # paths["test/mailers/previews"] does not guarantee config.autoload_paths
79
+ # is going to include them.
80
+ #
81
+ # If config.paths was accessed before, config.autoload_paths is going to
82
+ # have whatever paths["test/mailers/previews"] had when cached.
83
+ app.config.autoload_paths.concat(options.preview_paths)
74
84
  end
75
85
 
76
86
  initializer "action_mailer.compile_config_methods" do
@@ -79,18 +89,13 @@ module ActionMailer
79
89
  end
80
90
  end
81
91
 
82
- initializer "action_mailer.eager_load_actions" do
83
- ActiveSupport.on_load(:after_initialize) do
84
- ActionMailer::Base.descendants.each(&:action_methods) if config.eager_load
85
- end
86
- end
87
-
88
92
  config.after_initialize do |app|
89
93
  options = app.config.action_mailer
90
94
 
91
95
  if options.show_previews
92
96
  app.routes.prepend do
93
- get "/rails/mailers" => "rails/mailers#index", internal: true
97
+ get "/rails/mailers" => "rails/mailers#index", internal: true
98
+ get "/rails/mailers/download/*path" => "rails/mailers#download", internal: true
94
99
  get "/rails/mailers/*path" => "rails/mailers#preview", internal: true
95
100
  end
96
101
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionMailer # :nodoc:
4
+ # = Action Mailer \Rescuable
5
+ #
4
6
  # Provides
5
7
  # {rescue_from}[rdoc-ref:ActiveSupport::Rescuable::ClassMethods#rescue_from]
6
8
  # for mailers. Wraps mailer action processing, mail job processing, and mail
@@ -74,6 +74,15 @@ module ActionMailer
74
74
  end
75
75
  end
76
76
 
77
+ # Reads the fixture file for the given mailer.
78
+ #
79
+ # This is useful when testing mailers by being able to write the body of
80
+ # an email inside a fixture. See the testing guide for a concrete example:
81
+ # https://guides.rubyonrails.org/testing.html#revenge-of-the-fixtures
82
+ def read_fixture(action)
83
+ IO.readlines(File.join(Rails.root, "test", "fixtures", self.class.mailer_class.name.underscore, action))
84
+ end
85
+
77
86
  private
78
87
  def initialize_test_deliveries
79
88
  set_delivery_method :test
@@ -110,10 +119,6 @@ module ActionMailer
110
119
  def encode(subject)
111
120
  Mail::Encodings.q_value_encode(subject, charset)
112
121
  end
113
-
114
- def read_fixture(action)
115
- IO.readlines(File.join(Rails.root, "test", "fixtures", self.class.mailer_class.name.underscore, action))
116
- end
117
122
  end
118
123
 
119
124
  include Behavior
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/array/extract_options"
3
4
  require "active_job"
4
5
 
5
6
  module ActionMailer
@@ -33,10 +34,8 @@ module ActionMailer
33
34
  # end
34
35
  def assert_emails(number, &block)
35
36
  if block_given?
36
- original_count = ActionMailer::Base.deliveries.size
37
- perform_enqueued_jobs(only: ->(job) { delivery_job_filter(job) }, &block)
38
- new_count = ActionMailer::Base.deliveries.size
39
- assert_equal number, new_count - original_count, "#{number} emails expected, but #{new_count - original_count} were sent"
37
+ diff = capture_emails(&block).length
38
+ assert_equal number, diff, "#{number} emails expected, but #{diff} were sent"
40
39
  else
41
40
  assert_equal number, ActionMailer::Base.deliveries.size
42
41
  end
@@ -94,18 +93,50 @@ module ActionMailer
94
93
  end
95
94
 
96
95
  # Asserts that a specific email has been enqueued, optionally
97
- # matching arguments.
96
+ # matching arguments and/or params.
98
97
  #
99
98
  # def test_email
100
99
  # ContactMailer.welcome.deliver_later
101
100
  # assert_enqueued_email_with ContactMailer, :welcome
102
101
  # end
103
102
  #
103
+ # def test_email_with_parameters
104
+ # ContactMailer.with(greeting: "Hello").welcome.deliver_later
105
+ # assert_enqueued_email_with ContactMailer, :welcome, args: { greeting: "Hello" }
106
+ # end
107
+ #
104
108
  # def test_email_with_arguments
105
109
  # ContactMailer.welcome("Hello", "Goodbye").deliver_later
106
110
  # assert_enqueued_email_with ContactMailer, :welcome, args: ["Hello", "Goodbye"]
107
111
  # end
108
112
  #
113
+ # def test_email_with_named_arguments
114
+ # ContactMailer.welcome(greeting: "Hello", farewell: "Goodbye").deliver_later
115
+ # assert_enqueued_email_with ContactMailer, :welcome, args: [{ greeting: "Hello", farewell: "Goodbye" }]
116
+ # end
117
+ #
118
+ # def test_email_with_parameters_and_arguments
119
+ # ContactMailer.with(greeting: "Hello").welcome("Cheers", "Goodbye").deliver_later
120
+ # assert_enqueued_email_with ContactMailer, :welcome, params: { greeting: "Hello" }, args: ["Cheers", "Goodbye"]
121
+ # end
122
+ #
123
+ # def test_email_with_parameters_and_named_arguments
124
+ # ContactMailer.with(greeting: "Hello").welcome(farewell: "Goodbye").deliver_later
125
+ # assert_enqueued_email_with ContactMailer, :welcome, params: { greeting: "Hello" }, args: [{farewell: "Goodbye"}]
126
+ # end
127
+ #
128
+ # def test_email_with_parameterized_mailer
129
+ # ContactMailer.with(greeting: "Hello").welcome.deliver_later
130
+ # assert_enqueued_email_with ContactMailer.with(greeting: "Hello"), :welcome
131
+ # end
132
+ #
133
+ # def test_email_with_matchers
134
+ # ContactMailer.with(greeting: "Hello").welcome("Cheers", "Goodbye").deliver_later
135
+ # assert_enqueued_email_with ContactMailer, :welcome,
136
+ # params: ->(params) { /hello/i.match?(params[:greeting]) },
137
+ # args: ->(args) { /cheers/i.match?(args[0]) }
138
+ # end
139
+ #
109
140
  # If a block is passed, that block should cause the specified email
110
141
  # to be enqueued.
111
142
  #
@@ -123,13 +154,43 @@ module ActionMailer
123
154
  # ContactMailer.with(email: 'user@example.com').welcome.deliver_later
124
155
  # end
125
156
  # end
126
- def assert_enqueued_email_with(mailer, method, args: nil, queue: ActionMailer::Base.deliver_later_queue_name || "default", &block)
127
- args = if args.is_a?(Hash)
128
- [mailer.to_s, method.to_s, "deliver_now", params: args, args: []]
129
- else
130
- [mailer.to_s, method.to_s, "deliver_now", args: Array(args)]
157
+ def assert_enqueued_email_with(mailer, method, params: nil, args: nil, queue: nil, &block)
158
+ if mailer.is_a? ActionMailer::Parameterized::Mailer
159
+ params = mailer.instance_variable_get(:@params)
160
+ mailer = mailer.instance_variable_get(:@mailer)
131
161
  end
132
- assert_enqueued_with(job: mailer.delivery_job, args: args, queue: queue.to_s, &block)
162
+
163
+ if args.is_a?(Hash)
164
+ ActionMailer.deprecator.warn <<~MSG
165
+ Passing a Hash to the assert_enqueued_email_with :args kwarg causes the
166
+ Hash to be treated as params. This behavior is deprecated and will be
167
+ removed in Rails 7.2.
168
+
169
+ To specify a params Hash, use the :params kwarg:
170
+
171
+ assert_enqueued_email_with MyMailer, :my_method, params: { my_param: "value" }
172
+
173
+ Or, to specify named mailer args as a Hash, wrap the Hash in an array:
174
+
175
+ assert_enqueued_email_with MyMailer, :my_method, args: [{ my_arg: "value" }]
176
+ # OR
177
+ assert_enqueued_email_with MyMailer, :my_method, args: [my_arg: "value"]
178
+ MSG
179
+
180
+ params, args = args, nil
181
+ end
182
+
183
+ args = Array(args) unless args.is_a?(Proc)
184
+ queue ||= mailer.deliver_later_queue_name || ActiveJob::Base.default_queue_name
185
+
186
+ expected = ->(job_args) do
187
+ job_kwargs = job_args.extract_options!
188
+
189
+ [mailer.to_s, method.to_s, "deliver_now"] == job_args &&
190
+ params === job_kwargs[:params] && args === job_kwargs[:args]
191
+ end
192
+
193
+ assert_enqueued_with(job: mailer.delivery_job, args: expected, queue: queue.to_s, &block)
133
194
  end
134
195
 
135
196
  # Asserts that no emails are enqueued for later delivery.
@@ -151,6 +212,68 @@ module ActionMailer
151
212
  assert_enqueued_emails 0, &block
152
213
  end
153
214
 
215
+ # Delivers all enqueued emails. If a block is given, delivers all of the emails
216
+ # that were enqueued throughout the duration of the block. If a block is
217
+ # not given, delivers all the enqueued emails up to this point in the test.
218
+ #
219
+ # def test_deliver_enqueued_emails
220
+ # deliver_enqueued_emails do
221
+ # ContactMailer.welcome.deliver_later
222
+ # end
223
+ #
224
+ # assert_emails 1
225
+ # end
226
+ #
227
+ # def test_deliver_enqueued_emails_without_block
228
+ # ContactMailer.welcome.deliver_later
229
+ #
230
+ # deliver_enqueued_emails
231
+ #
232
+ # assert_emails 1
233
+ # end
234
+ #
235
+ # If the +:queue+ option is specified,
236
+ # then only the emails(s) enqueued to a specific queue will be performed.
237
+ #
238
+ # def test_deliver_enqueued_emails_with_queue
239
+ # deliver_enqueued_emails queue: :external_mailers do
240
+ # CustomerMailer.deliver_later_queue_name = :external_mailers
241
+ # CustomerMailer.welcome.deliver_later # will be performed
242
+ # EmployeeMailer.deliver_later_queue_name = :internal_mailers
243
+ # EmployeeMailer.welcome.deliver_later # will not be performed
244
+ # end
245
+ #
246
+ # assert_emails 1
247
+ # end
248
+ #
249
+ # If the +:at+ option is specified, then only delivers emails enqueued to deliver
250
+ # immediately or before the given time.
251
+ def deliver_enqueued_emails(queue: nil, at: nil, &block)
252
+ perform_enqueued_jobs(only: ->(job) { delivery_job_filter(job) }, queue: queue, at: at, &block)
253
+ end
254
+
255
+ # Returns any emails that are sent in the block.
256
+ #
257
+ # def test_emails
258
+ # emails = capture_emails do
259
+ # ContactMailer.welcome.deliver_now
260
+ # end
261
+ # assert_equal "Hi there", emails.first.subject
262
+ #
263
+ # emails = capture_emails do
264
+ # ContactMailer.welcome.deliver_now
265
+ # ContactMailer.welcome.deliver_later
266
+ # end
267
+ # assert_equal "Hi there", emails.first.subject
268
+ # end
269
+ def capture_emails(&block)
270
+ original_count = ActionMailer::Base.deliveries.size
271
+ deliver_enqueued_emails(&block)
272
+ new_count = ActionMailer::Base.deliveries.size
273
+ diff = new_count - original_count
274
+ ActionMailer::Base.deliveries.last(diff)
275
+ end
276
+
154
277
  private
155
278
  def delivery_job_filter(job)
156
279
  job_class = job.is_a?(Hash) ? job.fetch(:job) : job.class
@@ -4,7 +4,7 @@ require_relative "gem_version"
4
4
 
5
5
  module ActionMailer
6
6
  # Returns the currently loaded version of Action Mailer as a
7
- # <tt>Gem::Version</tt>.
7
+ # +Gem::Version+.
8
8
  def self.version
9
9
  gem_version
10
10
  end
data/lib/action_mailer.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2004-2022 David Heinemeier Hansson
4
+ # Copyright (c) David Heinemeier Hansson
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the
@@ -25,6 +25,7 @@
25
25
 
26
26
  require "abstract_controller"
27
27
  require "action_mailer/version"
28
+ require "action_mailer/deprecator"
28
29
 
29
30
  # Common Active Support usage in Action Mailer
30
31
  require "active_support"
@@ -34,6 +35,7 @@ require "active_support/core_ext/module/attr_internal"
34
35
  require "active_support/core_ext/string/inflections"
35
36
  require "active_support/lazy_load_hooks"
36
37
 
38
+ # :include: actionmailer/README.rdoc
37
39
  module ActionMailer
38
40
  extend ::ActiveSupport::Autoload
39
41
 
@@ -42,6 +44,7 @@ module ActionMailer
42
44
  end
43
45
 
44
46
  autoload :Base
47
+ autoload :Callbacks
45
48
  autoload :DeliveryMethods
46
49
  autoload :InlinePreviewInterceptor
47
50
  autoload :MailHelper
@@ -52,12 +55,17 @@ module ActionMailer
52
55
  autoload :TestHelper
53
56
  autoload :MessageDelivery
54
57
  autoload :MailDeliveryJob
58
+ autoload :QueuedDelivery
55
59
 
56
60
  def self.eager_load!
57
61
  super
58
62
 
59
63
  require "mail"
60
64
  Mail.eager_autoload!
65
+
66
+ Base.descendants.each do |mailer|
67
+ mailer.eager_load! unless mailer.abstract?
68
+ end
61
69
  end
62
70
  end
63
71
 
@@ -65,6 +73,6 @@ autoload :Mime, "action_dispatch/http/mime_type"
65
73
 
66
74
  ActiveSupport.on_load(:action_view) do
67
75
  ActionView::Base.default_formats ||= Mime::SET.symbols
68
- ActionView::Template::Types.delegate_to Mime
76
+ ActionView::Template.mime_types_implementation = Mime
69
77
  ActionView::LookupContext::DetailsKey.clear
70
78
  end
@@ -1,16 +1,20 @@
1
1
  Description:
2
- ============
3
2
  Generates a new mailer and its views. Passes the mailer name, either
4
3
  CamelCased or under_scored, and an optional list of emails as arguments.
5
4
 
6
5
  This generates a mailer class in app/mailers and invokes your template
7
6
  engine and test framework generators.
8
7
 
9
- Example:
10
- ========
11
- bin/rails generate mailer Notifications signup forgot_password invoice
8
+ Examples:
9
+ `bin/rails generate mailer sign_up`
10
+
11
+ creates a sign up mailer class, views, and test:
12
+ Mailer: app/mailers/sign_up_mailer.rb
13
+ Views: app/views/sign_up_mailer/signup.text.erb [...]
14
+ Test: test/mailers/sign_up_mailer_test.rb
15
+
16
+ `bin/rails generate mailer notifications sign_up forgot_password invoice`
17
+
18
+ creates a notifications mailer with sign_up, forgot_password, and invoice actions.
19
+
12
20
 
13
- creates a Notifications mailer class, views, and test:
14
- Mailer: app/mailers/notifications_mailer.rb
15
- Views: app/views/notifications_mailer/signup.text.erb [...]
16
- Test: test/mailers/notifications_mailer_test.rb