actionmailer 4.2.11.2 → 6.0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +53 -102
- 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 +6 -4
- 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
|
|