<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Flvorful Bloggage: Deep in Rails: ActionMailer#deliver Part II</title>
    <link>http://blog.flvorful.com/articles/2009/11/22/deep-in-rails-actionmailer-deliver-part-ii</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Deep in Rails: ActionMailer#deliver Part II</title>
      <description>&lt;p&gt;When we left off &lt;a href="http://blog.flvorful.com/articles/2009/11/15/deep-in-rails-actionmailer-deliver-part-i"&gt;last&lt;/a&gt;, we were just about to get into rendering the message.  Let&#8217;s recap that code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(line 553 action_mailer/base.rb)
def render_message(method_name, body)
  if method_name.respond_to?(:content_type)
    @current_template_content_type = method_name.content_type
  end
  render :file =&amp;gt; method_name, :body =&amp;gt; body
ensure
  @current_template_content_type = nil
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When we call &lt;code&gt;render_message&lt;/code&gt; in &lt;code&gt;create!&lt;/code&gt;, we call it with &lt;code&gt;@template&lt;/code&gt; and &lt;code&gt;@body&lt;/code&gt;, let&#8217;s see what those get set to inside of &lt;code&gt;render_message&lt;/code&gt; for our example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@template   = method_name     =&amp;gt; "contact_form" 
@body       = body            =&amp;gt; {:message=&amp;gt;"Send this message"}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the beginning of render_message &lt;code&gt;@body&lt;/code&gt; is set to the hash of instance variables that we set in our &lt;code&gt;contact_form&lt;/code&gt; method in our mailer.  Once we are finished processing, that hash will be gone and &lt;code&gt;@body&lt;/code&gt; will be replaced with the full rendered message.&lt;/p&gt;
&lt;p&gt;Next, we see that we want to set the &lt;code&gt;@current_template_content_type&lt;/code&gt; instance variable to the proper content type.  This is mainly used for multipart so that if render is passed one of those fancy &lt;code&gt;ActionView::ReloadableTemplate&lt;/code&gt; objects it renders it with the proper parser. Since we did not specify a content_type the method_name &#8220;contact_form&#8221; is passed and we get to skip over that part and go straight to the meat:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;render :file =&amp;gt; method_name, :body =&amp;gt; body&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is not the same render from &lt;code&gt;ActionController&lt;/code&gt; or &lt;code&gt;ActionView&lt;/code&gt;, but it does use the AV template render methods.  Let&#8217;s take a look at the definition:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(line 562 action_mailer/base.rb)
def render(opts)
  body = opts.delete(:body)
  if opts[:file] &amp;#38;&amp;#38; (opts[:file] !~ /\// &amp;#38;&amp;#38; !opts[:file].respond_to?(:render))
    opts[:file] = "#{mailer_name}/#{opts[:file]}" 
  end

  begin
    old_template, @template = @template, initialize_template_class(body)
    layout = respond_to?(:pick_layout, true) ? pick_layout(opts) : false
    @template.render(opts.merge(:layout =&amp;gt; layout))
  ensure
    @template = old_template
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the params with our example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;opts =&amp;gt; {
  :file =&amp;gt; "contact_form",
  :body =&amp;gt; {:message=&amp;gt;"Send this message"}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first thing we do is set the variable &lt;code&gt;body&lt;/code&gt; to &lt;code&gt;opts[:body]&lt;/code&gt; and delete it from the options hash (this is all done in one stroke by the call &lt;code&gt;delete&lt;/code&gt; which returns the value that was deleted).  Next, we test to see if &lt;code&gt;opts[:file]&lt;/code&gt; does not match &#8220;/&#8221; and does not respond to render then we set &lt;code&gt;opts[:file]&lt;/code&gt; to the same thing but prepended with the mailer_name, in our case &#8220;message_mailer&#8221;.&lt;/p&gt;
&lt;p&gt;Now we are getting to the real meat. First, we need to set some quick variables before we render.  Here are the 2 lines we will be examining next:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;old_template, @template = @template, initialize_template_class(body)
layout = respond_to?(:pick_layout, true) ? pick_layout(opts) : false&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the first line we are swapping out the current &lt;code&gt;@template&lt;/code&gt; variable with the result of &lt;code&gt;initialize_template_class(body)&lt;/code&gt; and storing the old value in &lt;code&gt;old_template&lt;/code&gt;.  Here is the definition of &lt;code&gt;initialize_template_class&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(line 603 action_mailer/base.rb)
def initialize_template_class(assigns)
  template = ActionView::Base.new(self.class.view_paths, assigns, self)
  template.template_format = default_template_format
  template
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and &lt;code&gt;assigns&lt;/code&gt; gets set to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;body =&amp;gt; {:message=&amp;gt;"Send this message"}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first thing we see is that we create a var named &lt;code&gt;template&lt;/code&gt; that is a new instantiation of &lt;code&gt;ActionView::Base&lt;/code&gt; with the &lt;code&gt;view_paths&lt;/code&gt;, &lt;code&gt;assigns&lt;/code&gt;, and the &lt;code&gt;model&lt;/code&gt; (MessageMailer in our example) passed to it. Let&#8217;s dig in and cross over to &lt;code&gt;ActionView::Base&lt;/code&gt; and look at &lt;code&gt;initialize&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(line 221 action_pack/action_view/base.rb)
def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil)#:nodoc:
  @assigns = assigns_for_first_render
  @assigns_added = nil
  @controller = controller
  @helpers = ProxyModule.new(self)
  self.view_paths = view_paths
  @_first_render = nil
  @_current_render = nil
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the params with our example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;view_paths               =&amp;gt; ["/example_app/app/views"]
assigns_for_first_render =&amp;gt; {:message=&amp;gt;"Send this message"}
controller               =&amp;gt; #&amp;lt;MessageMailer:0x34a579c 
                @action_name="contact_form", 
                @subject="Im contacting you", 
                @content_type="text/plain", 
                @implicit_parts_order=["text/html", "text/enriched", "text/plain"], 
                @from="jake@somewhere.com", 
                @sent_on=Sun Nov 08 11:34:17 -0600 2009, 
                @headers={}, 
                @default_template_name="contact_form", 
                @mime_version="1.0", 
                @body={:message=&amp;gt;"Send this message"}, 
                @mailer_name="message_mailer", 
                @recipients="someemail@somedomain.com", 
                @parts=[], 
                @template="contact_form", 
                @charset="utf-8"&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This allows us to wrap the mailers view around the &lt;code&gt;ActionView&lt;/code&gt; templating system and reuse the rendering module from &lt;code&gt;ActionView&lt;/code&gt; in AM. This also stores our body variables for use inside of our view. Now that we have a template, we need to initialize the &lt;code&gt;template_format&lt;/code&gt; with our mailer&#8217;s default template format.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;template.template_format = default_template_format&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#8217;s open up the definition for default_template_format&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(line 577 action_mailer/base.rb)
def default_template_format
  if @current_template_content_type
    Mime::Type.lookup(@current_template_content_type).to_sym
  else
    :html
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This method checks the &lt;code&gt;@current_template_content_type&lt;/code&gt; ivar and returns the proper mime-type.  This is used as a switch by the renderer.  If you dont explicitly set the content type AM defaults to &lt;span class="caps"&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt;&lt;/span&gt; and your message is rendered in &lt;span class="caps"&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt;&lt;/span&gt; mode.  Since we didnt define a &lt;code&gt;content_type&lt;/code&gt; in our example &lt;code&gt;@current_template_content_type&lt;/code&gt; is nil and :html will be returned for the &lt;code&gt;default_template_format&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After that we return the created template instance and that gets us through the &lt;code&gt;initialize_template_class&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;So now that we have set the &lt;code&gt;@template&lt;/code&gt; ivar in:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;old_template, @template = @template, initialize_template_class(body)
layout = respond_to?(:pick_layout, true) ? pick_layout(opts) : false&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We move down to setting the layout for the mailer.  In Rails you have the ability to use layouts just like in regular views. In our case, if we wanted to use a layout, we would have to add a file named &lt;code&gt;message_mailer.html.erb&lt;/code&gt; in &lt;code&gt;app/views/layouts&lt;/code&gt;.  The other option is specifying a layout name in our mailer model (just like we would in a controller).  So we could define MessageMailer as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class MessageMailer &amp;lt; ActionMailer::Base
  layout "my_email_layout" 
  def contact_form(msg_from, message)
    ...
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In that case, we would need a file named &lt;code&gt;my_email_layout.html.erb&lt;/code&gt; in our layouts directory.  Since we include &lt;code&gt;ActionController::Layout&lt;/code&gt; in AM::Base our model will respond to &lt;code&gt;pick_layout&lt;/code&gt;.  This is the method that will determine the layout needed for the renderer. Let&#8217;s dive into &lt;code&gt;pick_layout&lt;/code&gt;, which is defined in &lt;code&gt;ActionController::Layout&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# (line 229 action_pack/action_controller/layout.rb)
def pick_layout(options)
  if options.has_key?(:layout)
    case layout = options.delete(:layout)
    when FalseClass
      nil
    when NilClass, TrueClass
      active_layout if action_has_layout? &amp;#38;&amp;#38; candidate_for_layout?(:template =&amp;gt; default_template_name)
    else
      active_layout(layout, :html_fallback =&amp;gt; true)
    end
  else
    active_layout if action_has_layout? &amp;#38;&amp;#38; candidate_for_layout?(options)
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the params for our example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;options =&amp;gt; {:file=&amp;gt;"message_mailer/contact_form"}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first part of &lt;code&gt;pick_layout&lt;/code&gt; checks for the key &lt;code&gt;:layout&lt;/code&gt; in options and since we didnt define it in our example we will skip over it and straight to the else part of the conditional:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;active_layout if action_has_layout? &amp;#38;&amp;#38; candidate_for_layout?(options)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, we call the method &lt;code&gt;active_layout&lt;/code&gt;  if action_has_layout? returns true and candidate_for_layout?(options) returns true.  &lt;code&gt;action_has_layout?&lt;/code&gt; is a simple method to check if this action or mailer method has a layout and is basically making sure that your :except and :only actions render properly.  Let&#8217;s take a look at action_has_layout? with our example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# (line 244 action_pack/action_controller/layout.rb)
def action_has_layout?
  if conditions = self.class.layout_conditions
    case
      when only = conditions[:only]
        only.include?(action_name)
      when except = conditions[:except]
        !except.include?(action_name)
      else
        true
    end
  else
    true
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and &lt;code&gt;conditions&lt;/code&gt; would be:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;conditions =&amp;gt; nil&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we are not setting a layout for our message the method &lt;code&gt;self.class.layout_conditions&lt;/code&gt; returns nil.  &lt;code&gt;layout_conditions&lt;/code&gt; is a class method on AM that reads the attribute accessor hash &lt;code&gt;layout_conditions&lt;/code&gt;.  These conditions are written when you make the call:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;layout "my_template" # or layout "my_template", :except =&amp;gt; "some_message"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This writes all your conditions to a attribute hash for easy reading and subclassing.  Since our example returns nil for &lt;code&gt;layout_conditions&lt;/code&gt; we end up at the outer else statement and return true out of this method and on to &lt;code&gt;candidate_for_layout?(options)&lt;/code&gt;.  This is a base method is written in layout.rb and overridden in AM::base.rb:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# (line 585 action_mailer/base.rb)
def candidate_for_layout?(options)
  !self.view_paths.find_template(default_template_name, default_template_format).exempt_from_layout?
rescue ActionView::MissingTemplate
  return true
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and our paramaters and extra variables/methods :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;options =&amp;gt; {:file=&amp;gt;"message_mailer/contact_form"}
default_template_name =&amp;gt; "contact_form" 
default_template_format =&amp;gt; :html&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this method, we are checking to see if there is a template with the above params.  Since we dont have any layouts Rails throws an &lt;code&gt;ActionView::MissingTemplate&lt;/code&gt; exception which we catch and just return true from it.  This sets up the final part of &lt;code&gt;pick_layout&lt;/code&gt; which is &lt;code&gt;active_layout&lt;/code&gt;.  Here is the definition for that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# (line 201 action_pack/action_controller/layout.rb)
def active_layout(passed_layout = nil, options = {})
  layout = passed_layout || default_layout
  return layout if layout.respond_to?(:render)

  active_layout = case layout
    when Symbol then __send__(layout)
    when Proc   then layout.call(self)
    else layout
  end

  find_layout(active_layout, default_template_format, options[:html_fallback]) if active_layout
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In our case, we dont pass anything to active_layout so the first line will get set to &lt;code&gt;default_layout&lt;/code&gt;, which is a private method that looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# (line 220 action_pack/action_controller/layout.rb)
def default_layout #:nodoc:
  layout = self.class.read_inheritable_attribute(:layout)
  return layout unless self.class.read_inheritable_attribute(:auto_layout)
  find_layout(layout, default_template_format)
rescue ActionView::MissingTemplate
  nil
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we didnt set a layout, the first line will return &lt;code&gt;nil&lt;/code&gt; and the second line will return that value because &lt;code&gt;auto_layout&lt;/code&gt; will also be nil.  When we get back to &lt;code&gt;active_layout&lt;/code&gt;, the variable &lt;code&gt;layout&lt;/code&gt; is set to &lt;code&gt;nil&lt;/code&gt;. The variable &lt;code&gt;active_layout&lt;/code&gt; gets set to &lt;code&gt;nil&lt;/code&gt; as well since we are layout-less.  Now we get to &lt;code&gt;find_layout&lt;/code&gt; which doesnt get called in our example because &lt;code&gt;active_layout&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt;.  That&#8217;s it, we are now ready to do the main rendering.  Let&#8217;s look at the code again:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(line 562 action_mailer/base.rb)
def render(opts)
  ...
  begin
    old_template, @template = @template, initialize_template_class(body)
    layout = respond_to?(:pick_layout, true) ? pick_layout(opts) : false
    @template.render(opts.merge(:layout =&amp;gt; layout))
  ensure
    @template = old_template
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the params and current variables with our example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;opts =&amp;gt; {
  :file =&amp;gt; "contact_form",
  :body =&amp;gt; {:message=&amp;gt;"Send this message"}
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;old_template  =&amp;gt; "contact_form" 
@template =&amp;gt; #&amp;lt;ActionView::Base:0x3496c10 
                @template_format=:html, 
                @assigns={:message=&amp;gt;"Send this message"}, 
                @helpers=#&amp;lt;ActionView::Base::ProxyModule:0x3496b84&amp;gt;, 
                @controller=#&amp;lt;MessageMailer:0x34a5814 
                @action_name="contact_form", 
                @subject="Im contacting you", 
                @content_type="text/plain", 
                @implicit_parts_order=["text/html", "text/enriched", "text/plain"], 
                @from="jake@somewhere.com", 
                @sent_on=Sun Nov 08 18:15:42 -0600 2009, 
                @headers={}, 
                @default_template_name="contact_form", 
                @mime_version="1.0", 
                @body={:message=&amp;gt;"Send this message"}, 
                @mailer_name="message_mailer", 
                @recipients="someemail@somedomain.com", 
                @parts=[], 
                @template=#&amp;lt;ActionView::Base:0x3496c10 ...&amp;gt;, 
                @charset="utf-8"&amp;gt;, 
                @_current_render=nil, 
                @assigns_added=nil, 
                @_first_render=nil,
                @view_paths=["/example_app/app/views"]&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So now we see that &lt;code&gt;layout&lt;/code&gt; ends up being nil in our example which we then pass on to &lt;code&gt;@template.render&lt;/code&gt; along with our original options.  Now we&#8217;ll jump into &lt;code&gt;render&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# (line 201 action_view/base.rb)
def render(options = {}, local_assigns = {}, &amp;#38;block) #:nodoc:
  local_assigns ||= {}

  case options
  when Hash
    options = options.reverse_merge(:locals =&amp;gt; {})
    if options[:layout]
      _render_with_layout(options, local_assigns, &amp;#38;block)
    elsif options[:file]
      template = self.view_paths.find_template(options[:file], template_format)
      template.render_template(self, options[:locals])
    elsif options[:partial]
      render_partial(options)
    elsif options[:inline]
      InlineTemplate.new(options[:inline], options[:type]).render(self, options[:locals])
    elsif options[:text]
      options[:text]
    end
  when :update
    update_page(&amp;#38;block)
  else
    render_partial(:partial =&amp;gt; options, :locals =&amp;gt; local_assigns)
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and our passed in params:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;options =&amp;gt; {:file=&amp;gt;"message_mailer/contact_form", :layout=&amp;gt;nil}
local_assigns =&amp;gt; {}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since &lt;code&gt;options&lt;/code&gt; is a Hash, we jump right in and first merge in &lt;code&gt;:locals =&amp;gt; {}&lt;/code&gt; with &lt;code&gt;options&lt;/code&gt;.  &lt;code&gt;options[:layout]&lt;/code&gt; returns nil so we skip that statement and go into the &lt;code&gt;options[:file]&lt;/code&gt; conditional&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;template = self.view_paths.find_template(options[:file], template_format)
template.render_template(self, options[:locals])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, we search out the template from the AM models &lt;code&gt;view_paths&lt;/code&gt; with our file and the &lt;code&gt;temlpate_format&lt;/code&gt;, which in our case is &lt;code&gt;:html&lt;/code&gt;.  &lt;code&gt;view_paths&lt;/code&gt; is an instance method in &lt;code&gt;ActionView::Base&lt;/code&gt; that accesses the attribute &lt;code&gt;@view_paths&lt;/code&gt; which holds an instance of &lt;code&gt; ActionView::PathSet&lt;/code&gt;. This is a helper class that wraps an array with some pretty handy methods, one of which is &lt;code&gt;find_template&lt;/code&gt;. This helper class stores each of the view_paths as a &lt;code&gt;ActionView::ReloadableTemplate::ReloadablePath&lt;/code&gt; object.  This allows us to do other cooler things which we go over later.  In our case, &lt;code&gt;view_paths&lt;/code&gt; returns:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;self.view_paths =&amp;gt; ["/example_app/app/views"]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#8217;s dive into &lt;code&gt;find_template&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# (line 201 action_pack/action_view/paths.rb)
def find_template(original_template_path, format = nil, html_fallback = true)
  return original_template_path if original_template_path.respond_to?(:render)
  template_path = original_template_path.sub(/^\//, '')

  each do |load_path|
    if format &amp;#38;&amp;#38; (template = load_path["#{template_path}.#{I18n.locale}.#{format}"])
      return template
    elsif format &amp;#38;&amp;#38; (template = load_path["#{template_path}.#{format}"])
      return template
    elsif template = load_path["#{template_path}.#{I18n.locale}"]
      return template
    elsif template = load_path[template_path]
      return template
    # Try to find html version if the format is javascript
    elsif format == :js &amp;#38;&amp;#38; html_fallback &amp;#38;&amp;#38; template = load_path["#{template_path}.#{I18n.locale}.html"]
      return template
    elsif format == :js &amp;#38;&amp;#38; html_fallback &amp;#38;&amp;#38; template = load_path["#{template_path}.html"]
      return template
    end
  end

  return Template.new(original_template_path, original_template_path =~ /\A\// ? "" : ".") if File.file?(original_template_path)

  raise MissingTemplate.new(self, original_template_path, format)
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and our params:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;original_template_path =&amp;gt; "message_mailer/contact_form" 
format =&amp;gt; :html&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first line just returns back if we have a full fledged ActionView model that responds to render.  Since we dont, we keep going and see that the next line makes sure that our &lt;code&gt;original_template_path&lt;/code&gt; isnt an absolute path by removing the initial &#8220;/&#8221; if it is there and storing the final result in &lt;code&gt;template_path&lt;/code&gt;.  Next, we iterate over ourselves and do some checking (remember, PathSet is a subclass of Array, so we can call &lt;code&gt;each&lt;/code&gt; and iterate over the contents internally).  In our example, we end up executing the line:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;elsif template = load_path[template_path]
  return template&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is part of the fanciness of &lt;code&gt;ActionView::ReloadableTemplate::ReloadablePath&lt;/code&gt;.  One of the methods implemented is &lt;code&gt;[]&lt;/code&gt; which works like a hash and pulls out the proper &lt;code&gt;ReloadableTemplate&lt;/code&gt; from the paths array, in our case it&#8217;s&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;template =&amp;gt; #&amp;lt;ActionView::ReloadableTemplate:0x34a2ad8 
              @base_path="message_mailer", 
              @template_path="message_mailer/contact_form.erb", 
              @_memoized_path=["message_mailer/contact_form.erb"], 
              @name="contact_form", 
              @previously_last_modified=Sat Nov 07 10:32:50 -0600 2009, 
              @_memoized_method_segment=["app47views47message_mailer47contact_form46erb"], 
              @format=nil, 
              @filename="/example_app/app/views/message_mailer/contact_form.erb", 
              @_memoized_relative_path=["app/views/message_mailer/contact_form.erb"], 
              @extension="erb", 
              @locale=nil, 
              @_memoized_path_without_extension=["message_mailer/contact_form"], 
              @_memoized_method_name_without_locals=["_run_erb_app47views47message_mailer47contact_form46erb"], 
              @load_path="/example_app/app/views"&amp;gt;

So we found the proper view and we are now done with @find_template@. Back to @render@:&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# (line 201 action_pack/action_view/base.rb)
def render(options = {}, local_assigns = {}, &amp;#38;block) #:nodoc:
  local_assigns ||= {}

  case options
  when Hash
    ...
    elsif options[:file]
      template = self.view_paths.find_template(options[:file], template_format)
      template.render_template(self, options[:locals])
    elsif options[:partial]
      ...
    end
  when :update
    ...
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next line renders the template with any locals (in our case there are none). Before we dive into &lt;code&gt;render_template&lt;/code&gt; &#8216;s definition, let&#8217;s take a look at the view we created for our example message:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
(message_mailer/contact_form.erb)

Hi,

I am contacting you with this message:

&amp;lt;%= @message %&amp;gt;

Thanks

Jake
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A ridiculously simple mailer view for our equally ridiculously simple mailer message.  Back to &lt;code&gt;render_template&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# (line 193 action_pack/action_view/template.rb)
def render_template(view, local_assigns = {})
  render(view, local_assigns)
rescue Exception =&amp;gt; e
  raise e unless filename
  if TemplateError === e
    e.sub_template_of(self)
    raise e
  else
    raise TemplateError.new(self, view.assigns, e)
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and our current params:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;view  =&amp;gt; #&amp;lt;ActionView::Base:0x3496c10 
              @template_format=:html, 
              @assigns={:message=&amp;gt;"Send this message"}, 
              @helpers=#&amp;lt;ActionView::Base::ProxyModule:0x3496b84&amp;gt;, 
              @controller=#&amp;lt;MessageMailer:0x34a5814 
              @action_name="contact_form", 
              @subject="Im contacting you", 
              @content_type="text/plain", 
              @implicit_parts_order=["text/html", "text/enriched", "text/plain"], 
              @from="jake@somewhere.com", 
              @sent_on=Mon Nov 09 20:09:58 -0600 2009, 
              @headers={}, 
              @default_template_name="contact_form", 
              @mime_version="1.0", 
              @body={:message=&amp;gt;"Send this message"}, 
              @mailer_name="message_mailer", 
              @recipients="someemail@somedomain.com", 
              @parts=[], 
              @template=#&amp;lt;ActionView::Base:0x3496c10 ...&amp;gt;, 
              @charset="utf-8"&amp;gt;, 
              @_current_render=nil, 
              @assigns_added=nil, 
              @_first_render=nil, 
              @view_paths=["/example_app/app/views"]&amp;gt;
local_assigns =&amp;gt; {}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we can see, &lt;code&gt;render_template&lt;/code&gt; is a relatively simple method that delegates most of it&#8217;s work to &lt;code&gt;Renderable#render&lt;/code&gt;.  That&#8217;s where we are going next:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# (line 193 action_pack/action_view/renderable.rb)
def render(view, local_assigns = {})
  compile(local_assigns)

  view.with_template self do
    view.send(:_evaluate_assigns_and_ivars)
    view.send(:_set_controller_content_type, mime_type) if respond_to?(:mime_type)

    view.send(method_name(local_assigns), local_assigns) do |*names|
      ivar = :@_proc_for_layout
      if !view.instance_variable_defined?(:"@content_for_#{names.first}") &amp;#38;&amp;#38; view.instance_variable_defined?(ivar) &amp;#38;&amp;#38; (proc = view.instance_variable_get(ivar))
        view.capture(*names, &amp;#38;proc)
      elsif view.instance_variable_defined?(ivar = :"@content_for_#{names.first || :layout}")
        view.instance_variable_get(ivar)
      end
    end
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Whew, that&#8217;s it for this week.  Next week, we get super deep into rendering and see how Rails performs all of it&#8217;s rendering duties.&lt;/p&gt;</description>
      <pubDate>Sun, 22 Nov 2009 10:34:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:f885df96-11f6-4eb4-8052-490abe39604b</guid>
      <author>jake</author>
      <link>http://blog.flvorful.com/articles/2009/11/22/deep-in-rails-actionmailer-deliver-part-ii</link>
      <category>Rails</category>
      <category>rails</category>
      <category>action_mailer</category>
      <category>deep</category>
      <category>DIR</category>
      <category>part2</category>
    </item>
  </channel>
</rss>
