actionmailer 4.2.11.3 → 6.0.2.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +53 -107
- data/MIT-LICENSE +1 -1
- data/README.rdoc +8 -43
- data/lib/action_mailer.rb +22 -10
- data/lib/action_mailer/base.rb +291 -213
- data/lib/action_mailer/collector.rb +5 -3
- data/lib/action_mailer/delivery_job.rb +34 -3
- data/lib/action_mailer/delivery_methods.rb +15 -17
- data/lib/action_mailer/gem_version.rb +7 -5
- data/lib/action_mailer/inline_preview_interceptor.rb +12 -16
- data/lib/action_mailer/log_subscriber.rb +13 -7
- data/lib/action_mailer/mail_delivery_job.rb +38 -0
- data/lib/action_mailer/mail_helper.rb +16 -2
- data/lib/action_mailer/message_delivery.rb +79 -42
- data/lib/action_mailer/parameterized.rb +171 -0
- data/lib/action_mailer/preview.rb +52 -27
- data/lib/action_mailer/railtie.rb +41 -12
- data/lib/action_mailer/rescuable.rb +29 -0
- data/lib/action_mailer/test_case.rb +28 -10
- data/lib/action_mailer/test_helper.rb +107 -6
- data/lib/action_mailer/version.rb +3 -1
- data/lib/rails/generators/mailer/USAGE +3 -3
- data/lib/rails/generators/mailer/mailer_generator.rb +24 -5
- data/lib/rails/generators/mailer/templates/application_mailer.rb.tt +6 -0
- data/lib/rails/generators/mailer/templates/{mailer.rb → mailer.rb.tt} +2 -2
- metadata +26 -24
- data/lib/rails/generators/mailer/templates/application_mailer.rb +0 -4
@@ -0,0 +1,171 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMailer
|
4
|
+
# Provides the option to parameterize mailers in order to share instance variable
|
5
|
+
# setup, processing, and common headers.
|
6
|
+
#
|
7
|
+
# Consider this example that does not use parameterization:
|
8
|
+
#
|
9
|
+
# class InvitationsMailer < ApplicationMailer
|
10
|
+
# def account_invitation(inviter, invitee)
|
11
|
+
# @account = inviter.account
|
12
|
+
# @inviter = inviter
|
13
|
+
# @invitee = invitee
|
14
|
+
#
|
15
|
+
# subject = "#{@inviter.name} invited you to their Basecamp (#{@account.name})"
|
16
|
+
#
|
17
|
+
# mail \
|
18
|
+
# subject: subject,
|
19
|
+
# to: invitee.email_address,
|
20
|
+
# from: common_address(inviter),
|
21
|
+
# reply_to: inviter.email_address_with_name
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# def project_invitation(project, inviter, invitee)
|
25
|
+
# @account = inviter.account
|
26
|
+
# @project = project
|
27
|
+
# @inviter = inviter
|
28
|
+
# @invitee = invitee
|
29
|
+
# @summarizer = ProjectInvitationSummarizer.new(@project.bucket)
|
30
|
+
#
|
31
|
+
# subject = "#{@inviter.name.familiar} added you to a project in Basecamp (#{@account.name})"
|
32
|
+
#
|
33
|
+
# mail \
|
34
|
+
# subject: subject,
|
35
|
+
# to: invitee.email_address,
|
36
|
+
# from: common_address(inviter),
|
37
|
+
# reply_to: inviter.email_address_with_name
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# def bulk_project_invitation(projects, inviter, invitee)
|
41
|
+
# @account = inviter.account
|
42
|
+
# @projects = projects.sort_by(&:name)
|
43
|
+
# @inviter = inviter
|
44
|
+
# @invitee = invitee
|
45
|
+
#
|
46
|
+
# subject = "#{@inviter.name.familiar} added you to some new stuff in Basecamp (#{@account.name})"
|
47
|
+
#
|
48
|
+
# mail \
|
49
|
+
# subject: subject,
|
50
|
+
# to: invitee.email_address,
|
51
|
+
# from: common_address(inviter),
|
52
|
+
# reply_to: inviter.email_address_with_name
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# InvitationsMailer.account_invitation(person_a, person_b).deliver_later
|
57
|
+
#
|
58
|
+
# Using parameterized mailers, this can be rewritten as:
|
59
|
+
#
|
60
|
+
# class InvitationsMailer < ApplicationMailer
|
61
|
+
# before_action { @inviter, @invitee = params[:inviter], params[:invitee] }
|
62
|
+
# before_action { @account = params[:inviter].account }
|
63
|
+
#
|
64
|
+
# default to: -> { @invitee.email_address },
|
65
|
+
# from: -> { common_address(@inviter) },
|
66
|
+
# reply_to: -> { @inviter.email_address_with_name }
|
67
|
+
#
|
68
|
+
# def account_invitation
|
69
|
+
# mail subject: "#{@inviter.name} invited you to their Basecamp (#{@account.name})"
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# def project_invitation
|
73
|
+
# @project = params[:project]
|
74
|
+
# @summarizer = ProjectInvitationSummarizer.new(@project.bucket)
|
75
|
+
#
|
76
|
+
# mail subject: "#{@inviter.name.familiar} added you to a project in Basecamp (#{@account.name})"
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# def bulk_project_invitation
|
80
|
+
# @projects = params[:projects].sort_by(&:name)
|
81
|
+
#
|
82
|
+
# mail subject: "#{@inviter.name.familiar} added you to some new stuff in Basecamp (#{@account.name})"
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# InvitationsMailer.with(inviter: person_a, invitee: person_b).account_invitation.deliver_later
|
87
|
+
module Parameterized
|
88
|
+
extend ActiveSupport::Concern
|
89
|
+
|
90
|
+
included do
|
91
|
+
attr_accessor :params
|
92
|
+
end
|
93
|
+
|
94
|
+
module ClassMethods
|
95
|
+
# Provide the parameters to the mailer in order to use them in the instance methods and callbacks.
|
96
|
+
#
|
97
|
+
# InvitationsMailer.with(inviter: person_a, invitee: person_b).account_invitation.deliver_later
|
98
|
+
#
|
99
|
+
# See Parameterized documentation for full example.
|
100
|
+
def with(params)
|
101
|
+
ActionMailer::Parameterized::Mailer.new(self, params)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Mailer # :nodoc:
|
106
|
+
def initialize(mailer, params)
|
107
|
+
@mailer, @params = mailer, params
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
def method_missing(method_name, *args)
|
112
|
+
if @mailer.action_methods.include?(method_name.to_s)
|
113
|
+
ActionMailer::Parameterized::MessageDelivery.new(@mailer, method_name, @params, *args)
|
114
|
+
else
|
115
|
+
super
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def respond_to_missing?(method, include_all = false)
|
120
|
+
@mailer.respond_to?(method, include_all)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class DeliveryJob < ActionMailer::DeliveryJob # :nodoc:
|
125
|
+
def perform(mailer, mail_method, delivery_method, params, *args)
|
126
|
+
mailer.constantize.with(params).public_send(mail_method, *args).send(delivery_method)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class MessageDelivery < ActionMailer::MessageDelivery # :nodoc:
|
131
|
+
def initialize(mailer_class, action, params, *args)
|
132
|
+
super(mailer_class, action, *args)
|
133
|
+
@params = params
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
def processed_mailer
|
138
|
+
@processed_mailer ||= @mailer_class.new.tap do |mailer|
|
139
|
+
mailer.params = @params
|
140
|
+
mailer.process @action, *@args
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def enqueue_delivery(delivery_method, options = {})
|
145
|
+
if processed?
|
146
|
+
super
|
147
|
+
else
|
148
|
+
job = delivery_job_class
|
149
|
+
args = arguments_for(job, delivery_method)
|
150
|
+
job.set(options).perform_later(*args)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def delivery_job_class
|
155
|
+
if @mailer_class.delivery_job <= MailDeliveryJob
|
156
|
+
@mailer_class.delivery_job
|
157
|
+
else
|
158
|
+
Parameterized::DeliveryJob
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def arguments_for(delivery_job, delivery_method)
|
163
|
+
if delivery_job <= MailDeliveryJob
|
164
|
+
[@mailer_class.name, @action.to_s, delivery_method.to_s, params: @params, args: @args]
|
165
|
+
else
|
166
|
+
[@mailer_class.name, @action.to_s, delivery_method.to_s, @params, *@args]
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/descendants_tracker"
|
2
4
|
|
3
5
|
module ActionMailer
|
4
6
|
module Previews #:nodoc:
|
@@ -15,13 +17,12 @@ module ActionMailer
|
|
15
17
|
#
|
16
18
|
# config.action_mailer.show_previews = true
|
17
19
|
#
|
18
|
-
# Defaults to true for development environment
|
20
|
+
# Defaults to +true+ for development environment
|
19
21
|
#
|
20
22
|
mattr_accessor :show_previews, instance_writer: false
|
21
23
|
|
22
24
|
# :nodoc:
|
23
|
-
mattr_accessor :preview_interceptors, instance_writer: false
|
24
|
-
self.preview_interceptors = []
|
25
|
+
mattr_accessor :preview_interceptors, instance_writer: false, default: [ActionMailer::InlinePreviewInterceptor]
|
25
26
|
end
|
26
27
|
|
27
28
|
module ClassMethods
|
@@ -30,29 +31,53 @@ module ActionMailer
|
|
30
31
|
interceptors.flatten.compact.each { |interceptor| register_preview_interceptor(interceptor) }
|
31
32
|
end
|
32
33
|
|
34
|
+
# Unregister one or more previously registered Interceptors.
|
35
|
+
def unregister_preview_interceptors(*interceptors)
|
36
|
+
interceptors.flatten.compact.each { |interceptor| unregister_preview_interceptor(interceptor) }
|
37
|
+
end
|
38
|
+
|
33
39
|
# Register an Interceptor which will be called before mail is previewed.
|
34
40
|
# Either a class or a string can be passed in as the Interceptor. If a
|
35
|
-
# string is passed in it will be
|
41
|
+
# string is passed in it will be constantized.
|
36
42
|
def register_preview_interceptor(interceptor)
|
37
|
-
preview_interceptor =
|
43
|
+
preview_interceptor = interceptor_class_for(interceptor)
|
44
|
+
|
45
|
+
unless preview_interceptors.include?(preview_interceptor)
|
46
|
+
preview_interceptors << preview_interceptor
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Unregister a previously registered Interceptor.
|
51
|
+
# Either a class or a string can be passed in as the Interceptor. If a
|
52
|
+
# string is passed in it will be constantized.
|
53
|
+
def unregister_preview_interceptor(interceptor)
|
54
|
+
preview_interceptors.delete(interceptor_class_for(interceptor))
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def interceptor_class_for(interceptor)
|
60
|
+
case interceptor
|
38
61
|
when String, Symbol
|
39
62
|
interceptor.to_s.camelize.constantize
|
40
63
|
else
|
41
64
|
interceptor
|
42
65
|
end
|
43
|
-
|
44
|
-
unless preview_interceptors.include?(preview_interceptor)
|
45
|
-
preview_interceptors << preview_interceptor
|
46
66
|
end
|
47
|
-
end
|
48
67
|
end
|
49
68
|
end
|
50
69
|
|
51
70
|
class Preview
|
52
71
|
extend ActiveSupport::DescendantsTracker
|
53
72
|
|
73
|
+
attr_reader :params
|
74
|
+
|
75
|
+
def initialize(params = {})
|
76
|
+
@params = params
|
77
|
+
end
|
78
|
+
|
54
79
|
class << self
|
55
|
-
# Returns all mailer preview classes
|
80
|
+
# Returns all mailer preview classes.
|
56
81
|
def all
|
57
82
|
load_previews if descendants.empty?
|
58
83
|
descendants
|
@@ -61,54 +86,54 @@ module ActionMailer
|
|
61
86
|
# Returns the mail object for the given email name. The registered preview
|
62
87
|
# interceptors will be informed so that they can transform the message
|
63
88
|
# as they would if the mail was actually being delivered.
|
64
|
-
def call(email)
|
65
|
-
preview =
|
89
|
+
def call(email, params = {})
|
90
|
+
preview = new(params)
|
66
91
|
message = preview.public_send(email)
|
67
92
|
inform_preview_interceptors(message)
|
68
93
|
message
|
69
94
|
end
|
70
95
|
|
71
|
-
# Returns all of the available email previews
|
96
|
+
# Returns all of the available email previews.
|
72
97
|
def emails
|
73
98
|
public_instance_methods(false).map(&:to_s).sort
|
74
99
|
end
|
75
100
|
|
76
|
-
# Returns true if the email exists
|
101
|
+
# Returns +true+ if the email exists.
|
77
102
|
def email_exists?(email)
|
78
103
|
emails.include?(email)
|
79
104
|
end
|
80
105
|
|
81
|
-
# Returns true if the preview exists
|
106
|
+
# Returns +true+ if the preview exists.
|
82
107
|
def exists?(preview)
|
83
|
-
all.any?{ |p| p.preview_name == preview }
|
108
|
+
all.any? { |p| p.preview_name == preview }
|
84
109
|
end
|
85
110
|
|
86
|
-
# Find a mailer preview by its underscored class name
|
111
|
+
# Find a mailer preview by its underscored class name.
|
87
112
|
def find(preview)
|
88
|
-
all.find{ |p| p.preview_name == preview }
|
113
|
+
all.find { |p| p.preview_name == preview }
|
89
114
|
end
|
90
115
|
|
91
|
-
# Returns the underscored name of the mailer preview without the suffix
|
116
|
+
# Returns the underscored name of the mailer preview without the suffix.
|
92
117
|
def preview_name
|
93
|
-
name.sub(/Preview$/,
|
118
|
+
name.sub(/Preview$/, "").underscore
|
94
119
|
end
|
95
120
|
|
96
|
-
|
97
|
-
def load_previews
|
121
|
+
private
|
122
|
+
def load_previews
|
98
123
|
if preview_path
|
99
|
-
Dir["#{preview_path}/**/*_preview.rb"].each{ |file| require_dependency file }
|
124
|
+
Dir["#{preview_path}/**/*_preview.rb"].sort.each { |file| require_dependency file }
|
100
125
|
end
|
101
126
|
end
|
102
127
|
|
103
|
-
def preview_path
|
128
|
+
def preview_path
|
104
129
|
Base.preview_path
|
105
130
|
end
|
106
131
|
|
107
|
-
def show_previews
|
132
|
+
def show_previews
|
108
133
|
Base.show_previews
|
109
134
|
end
|
110
135
|
|
111
|
-
def inform_preview_interceptors(message)
|
136
|
+
def inform_preview_interceptors(message)
|
112
137
|
Base.preview_interceptors.each do |interceptor|
|
113
138
|
interceptor.previewing_email(message)
|
114
139
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_job/railtie"
|
2
4
|
require "action_mailer"
|
3
5
|
require "rails"
|
4
6
|
require "abstract_controller/railties/routes_helpers"
|
@@ -16,13 +18,19 @@ module ActionMailer
|
|
16
18
|
paths = app.config.paths
|
17
19
|
options = app.config.action_mailer
|
18
20
|
|
21
|
+
if app.config.force_ssl
|
22
|
+
options.default_url_options ||= {}
|
23
|
+
options.default_url_options[:protocol] ||= "https"
|
24
|
+
end
|
25
|
+
|
19
26
|
options.assets_dir ||= paths["public"].first
|
20
27
|
options.javascripts_dir ||= paths["public/javascripts"].first
|
21
28
|
options.stylesheets_dir ||= paths["public/stylesheets"].first
|
22
29
|
options.show_previews = Rails.env.development? if options.show_previews.nil?
|
30
|
+
options.cache_store ||= Rails.cache
|
23
31
|
|
24
32
|
if options.show_previews
|
25
|
-
options.preview_path
|
33
|
+
options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/mailers/previews" : nil
|
26
34
|
end
|
27
35
|
|
28
36
|
# make sure readers methods get compiled
|
@@ -38,14 +46,24 @@ module ActionMailer
|
|
38
46
|
register_preview_interceptors(options.delete(:preview_interceptors))
|
39
47
|
register_observers(options.delete(:observers))
|
40
48
|
|
41
|
-
|
42
|
-
|
43
|
-
if options.show_previews
|
44
|
-
app.routes.append do
|
45
|
-
get '/rails/mailers' => "rails/mailers#index"
|
46
|
-
get '/rails/mailers/*path' => "rails/mailers#preview"
|
47
|
-
end
|
49
|
+
if delivery_job = options.delete(:delivery_job)
|
50
|
+
self.delivery_job = delivery_job.constantize
|
48
51
|
end
|
52
|
+
|
53
|
+
options.each { |k, v| send("#{k}=", v) }
|
54
|
+
end
|
55
|
+
|
56
|
+
ActiveSupport.on_load(:action_dispatch_integration_test) do
|
57
|
+
include ActionMailer::TestHelper
|
58
|
+
include ActionMailer::TestCase::ClearTestDeliveries
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
initializer "action_mailer.set_autoload_paths" do |app|
|
63
|
+
options = app.config.action_mailer
|
64
|
+
|
65
|
+
if options.show_previews && options.preview_path
|
66
|
+
ActiveSupport::Dependencies.autoload_paths << options.preview_path
|
49
67
|
end
|
50
68
|
end
|
51
69
|
|
@@ -55,9 +73,20 @@ module ActionMailer
|
|
55
73
|
end
|
56
74
|
end
|
57
75
|
|
58
|
-
|
59
|
-
|
60
|
-
|
76
|
+
initializer "action_mailer.eager_load_actions" do
|
77
|
+
ActiveSupport.on_load(:after_initialize) do
|
78
|
+
ActionMailer::Base.descendants.each(&:action_methods) if config.eager_load
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
config.after_initialize do |app|
|
83
|
+
options = app.config.action_mailer
|
84
|
+
|
85
|
+
if options.show_previews
|
86
|
+
app.routes.prepend do
|
87
|
+
get "/rails/mailers" => "rails/mailers#index", internal: true
|
88
|
+
get "/rails/mailers/*path" => "rails/mailers#preview", internal: true
|
89
|
+
end
|
61
90
|
end
|
62
91
|
end
|
63
92
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionMailer #:nodoc:
|
4
|
+
# Provides +rescue_from+ for mailers. Wraps mailer action processing,
|
5
|
+
# mail job processing, and mail delivery.
|
6
|
+
module Rescuable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
include ActiveSupport::Rescuable
|
9
|
+
|
10
|
+
class_methods do
|
11
|
+
def handle_exception(exception) #:nodoc:
|
12
|
+
rescue_with_handler(exception) || raise(exception)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def handle_exceptions #:nodoc:
|
17
|
+
yield
|
18
|
+
rescue => exception
|
19
|
+
rescue_with_handler(exception) || raise
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def process(*)
|
24
|
+
handle_exceptions do
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,16 +1,35 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/test_case"
|
4
|
+
require "rails-dom-testing"
|
3
5
|
|
4
6
|
module ActionMailer
|
5
7
|
class NonInferrableMailerError < ::StandardError
|
6
8
|
def initialize(name)
|
7
|
-
super "Unable to determine the mailer to test from #{name}. "
|
8
|
-
"You'll need to specify it using tests YourMailer in your "
|
9
|
+
super "Unable to determine the mailer to test from #{name}. " \
|
10
|
+
"You'll need to specify it using tests YourMailer in your " \
|
9
11
|
"test case definition"
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
13
15
|
class TestCase < ActiveSupport::TestCase
|
16
|
+
module ClearTestDeliveries
|
17
|
+
extend ActiveSupport::Concern
|
18
|
+
|
19
|
+
included do
|
20
|
+
setup :clear_test_deliveries
|
21
|
+
teardown :clear_test_deliveries
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def clear_test_deliveries
|
27
|
+
if ActionMailer::Base.delivery_method == :test
|
28
|
+
ActionMailer::Base.deliveries.clear
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
14
33
|
module Behavior
|
15
34
|
extend ActiveSupport::Concern
|
16
35
|
|
@@ -24,6 +43,7 @@ module ActionMailer
|
|
24
43
|
setup :initialize_test_deliveries
|
25
44
|
setup :set_expected_mail
|
26
45
|
teardown :restore_test_deliveries
|
46
|
+
ActiveSupport.run_load_hooks(:action_mailer_test_case, self)
|
27
47
|
end
|
28
48
|
|
29
49
|
module ClassMethods
|
@@ -39,7 +59,7 @@ module ActionMailer
|
|
39
59
|
end
|
40
60
|
|
41
61
|
def mailer_class
|
42
|
-
if mailer =
|
62
|
+
if mailer = _mailer_class
|
43
63
|
mailer
|
44
64
|
else
|
45
65
|
tests determine_default_mailer(name)
|
@@ -55,7 +75,7 @@ module ActionMailer
|
|
55
75
|
end
|
56
76
|
end
|
57
77
|
|
58
|
-
|
78
|
+
private
|
59
79
|
|
60
80
|
def initialize_test_deliveries
|
61
81
|
set_delivery_method :test
|
@@ -82,11 +102,9 @@ module ActionMailer
|
|
82
102
|
def set_expected_mail
|
83
103
|
@expected = Mail.new
|
84
104
|
@expected.content_type ["text", "plain", { "charset" => charset }]
|
85
|
-
@expected.mime_version =
|
105
|
+
@expected.mime_version = "1.0"
|
86
106
|
end
|
87
107
|
|
88
|
-
private
|
89
|
-
|
90
108
|
def charset
|
91
109
|
"UTF-8"
|
92
110
|
end
|
@@ -96,7 +114,7 @@ module ActionMailer
|
|
96
114
|
end
|
97
115
|
|
98
116
|
def read_fixture(action)
|
99
|
-
IO.readlines(File.join(Rails.root,
|
117
|
+
IO.readlines(File.join(Rails.root, "test", "fixtures", self.class.mailer_class.name.underscore, action))
|
100
118
|
end
|
101
119
|
end
|
102
120
|
|