1 # Overriding ActionMailer to teach it about Engines...
5 # Initialize the mailer via the given +method_name+. The body will be
6 # rendered and a new TMail::Mail object created.
7 def create!(method_name, *parameters) #:nodoc:
8 initialize_defaults(method_name)
9 send(method_name, *parameters)
12 # If an explicit, textual body has not been set, we check assumptions.
13 unless String === @body
14 # First, we look to see if there are any likely templates that match,
15 # which include the content-type in their file name (i.e.,
16 # "the_template_file.text.html.rhtml", etc.). Only do this if parts
17 # have not already been specified manually.
19 templates = get_all_templates_for_action(@template)
21 #RAILS_DEFAULT_LOGGER.debug "template: #{@template}; templates: #{templates.inspect}"
25 # /app/views/<mailer object name> / <action>.something.rhtml
27 #templates = Dir.glob("#{template_path}/#{@template}.*")
29 # this loop expects an array of paths to actual template files which match
30 # the given action name
31 templates.each do |path|
32 # TODO: don't hardcode rhtml|rxml
33 basename = File.basename(path)
34 next unless md = /^([^\.]+)\.([^\.]+\.[^\+]+)\.(rhtml|rxml)$/.match(basename)
36 template_name = basename
37 content_type = md.captures[1].gsub('.', '/')
39 @parts << Part.new(:content_type => content_type,
40 :disposition => "inline", :charset => charset,
41 :body => render_message(template_name, @body))
44 @content_type = "multipart/alternative"
45 @parts = sort_parts(@parts, @implicit_parts_order)
49 # Then, if there were such templates, we check to see if we ought to
50 # also render a "normal" template (without the content type). If a
51 # normal template exists (or if there were no implicit parts) we render
53 template_exists = @parts.empty?
54 # template_exists ||= Dir.glob("#{template_path}/#{@template}.*").any? { |i| i.split(".").length == 2 }
55 template_exists ||= templates.any? do |i|
56 arr = File.basename(i).split(".")
57 (arr.length == 2) && (arr[0] == @template)
59 @body = render_message(@template, @body) if template_exists
61 # Finally, if there are other message parts and a textual body exists,
62 # we shift it onto the front of the parts and set the body to nil (so
63 # that create_mail doesn't try to render it in addition to the parts).
64 if !@parts.empty? && String === @body
65 @parts.unshift Part.new(:charset => charset, :body => @body)
70 # If this is a multipart e-mail add the mime_version if it is not
72 @mime_version ||= "1.0" if !@parts.empty?
74 # build the mail object itself
81 # JGA - Modified to pass the method name to initialize_template_class
83 body = opts.delete(:body)
84 initialize_template_class(body, opts[:file]).render(opts)
88 # Return all ActionView template paths from the app and all Engines
90 paths = [template_path]
91 Engines.each { |engine|
92 # add a path for every engine if one exists.
93 engine_template_path = File.join(engine.root, "app", "views", mailer_name)
94 paths << engine_template_path if File.exists?(engine_template_path)
99 # Returns a list of all template paths in the app and Engines
100 # which contain templates that might be used for the given action
101 def get_all_templates_for_action(action)
102 # can we trust uniq! to do this? i'm not sure...
105 template_paths.each { |path|
106 all_templates_for_path = Dir.glob(File.join(path, "#{action}*"))
107 all_templates_for_path.each { |template|
108 name = File.basename(template)
109 if !seen_names.include?(name)
111 templates << template
118 # Returns the first path to the given template in our
119 # app/Engine 'chain'.
120 def find_template_root_for(template)
121 all_paths = get_all_templates_for_action(template)
125 return File.dirname(all_paths[0])
129 # JGA - changed here to include the method name that we
130 # are interested in, so that we can re-locate the proper
132 def initialize_template_class(assigns, method_name)
133 engine_template = find_template_root_for(method_name)
134 action_view_class = Class.new(ActionView::Base).send(:include, master_helper_module)
135 action_view_class.new(engine_template, assigns, self)