<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>templating Archives | Clever Cloud</title>
	<atom:link href="https://stagingv6.cleverapps.io/blog/tag/templating/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>From Code to Product</description>
	<lastBuildDate>Thu, 28 Mar 2019 17:43:00 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2023/03/cropped-cropped-favicon-32x32.png</url>
	<title>templating Archives | Clever Cloud</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Really understand Rails templating</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2019/03/28/understanding-rails-templating-part-1/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Thu, 28 Mar 2019 17:43:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[rubyonrails]]></category>
		<category><![CDATA[templating]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2019/03/28/understanding-rails-templating-part-1/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" fetchpriority="high" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>As a web developer, my first framework ever was RubyOnRails and I still keep a particular affection among them.</p>
<p>So when the template rendering was first introduced to me, I understood how it worked on the top layers, used it and I was perfectly fine doing so, because rails’ Convention over Configuration is very powerful.</p>
<span id="more-2818"></span>

<p>But the part of me whom re coded several sys calls to understand how it works is craving to know what’s under the templates&#39; system in RoR, so let’s dive in!</p>
<p>But first of all, a warning. I’m not here to talk to you about how to use template rendering in rails, many great articles have been written on the subject already and the documentation is super explicit so if that is the reason you are here, I’d suggest you have a look <a href="https://guides.rubyonrails.org/layouts_and_rendering.html">here</a> or <a href="https://guides.rubyonrails.org/layouts_and_rendering.html#using-render">here</a>.</p>
<h2 id="how-to-trigger-template-rendering-process-">How to trigger template rendering process ?</h2>
<p>Actually there are <a href="https://evilmartians.com/chronicles/new-feature-in-rails-5-render-views-outside-of-actions" rel="noopener noreferrer" target="_blank">many fun ways</a> to trigger template rendering in Rails, but we will stick to controller here.</p>
<h3 id="1---convention-over-configuration">1 - Convention over configuration</h3>
<p>The very first thing you ever try, when you first launch a server on a <code>rails new my_project_name</code> brand-new project, is in the <a href="https://github.com/rails/rails/blob/master/railties/lib/rails/welcome_controller.rb">welcome controller</a> provided by rails. Please note the <code>layout: false</code>, we’ll get back to that later.</p>
<pre><code class="language-ruby">class Rails::WelcomeController &lt; Rails::ApplicationController # :nodoc:
  layout: false

  def index
  end
end
</code></pre>
<pre><code class="language-text">Processing by Rails::WelcomeController#index as HTML
Rendering /Users/valeriane/.rvm/gems/ruby-2.5.1/gems/railties-5.1.6.1/lib/rails/templates/rails/welcome/index.html.erb
</code></pre>
<p>As we can see the index method is empty and the rendering of <code>/rails/templates/rails/welcome/index.html.erb</code> is processed automatically. <img src="https://edgeguides.rubyonrails.org/images/getting_started/rails_welcome.png" alt="ruby on rails default home page"></p>
<h3 id="2---explicit-call-to-render-method">2 - Explicit call to render method</h3>
<pre><code class="language-ruby">  def update
    @book= Book.find(params[:id])

    if @book.update(book_params)
      redirect_to(@book)
    else
      render &quot;edit&quot;
    end
  end
</code></pre>
<p>In this <code>update</code> method, we have an explicit call to the <a href="https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/renderer/renderer.rb#L21" rel="noopener noreferrer" target="_blank">render method</a> which is actually an <a href="https://guides.rubyonrails.org/action_view_overview.html" rel="noopener noreferrer" target="_blank">ActionView</a> helper.<br>If object update fails with given params, we want the user to be able to change theses params right away. So we ask Rails to render the <code>edit</code> view instead of the <code>update</code> view it would have rendered otherwise as we are in an <code>update</code> method.</p>
<p>You can render many formats (JavaScript, JSON, plain text…) and add a ton of options, so be sure to check the <a href="https://guides.rubyonrails.org/layouts_and_rendering.html#using-render" rel="noopener noreferrer" target="_blank">full documentation</a>.</p>
<h3 id="3---rendering-html-headers-only">3 - Rendering HTML headers only</h3>
<pre><code class="language-ruby">def show
  if !params[:id]
    head :bad_request
  else
    @book = Book.find(params[:id])
  end
end
</code></pre>
<p><a href="https://apidock.com/rails/v4.2.7/ActionController/Head/head" rel="noopener noreferrer" target="_blank">head method</a> is used to send specific headers only responses to the browser. Here the <code>:bad_request</code> symbol represents the 400 HTTP code. This usage is not suitable for production.<br>As this is not using the template rendering process we won&#39;t discuss <code>head</code> further here.</p>
<h3 id="4---hey-there-was-a-redirect_to-in-example-2">4 - Hey, there was a redirect_to in example 2!</h3>
<p>You are absolutely right.<br><code>redirect_to</code> is a method that sets the response by default to 302 HTTP code and adds default instructions to tell browsers which request to build next.<br>As for render there is a large list of options you can provide, <a href="https://api.rubyonrails.org/classes/ActionController/Redirecting.html#method-i-redirect_to" rel="noopener noreferrer" target="_blank">read the docs</a>!</p>
<p>Once this instruction is sent to the browser, nothing will happen until the server receives the new request built by the browser. At this point, the process of handling request will restart from the beginning and even if there is a new <code>redirect_to</code> in your way you will fatally end up encountering a head method, an implicit or an explicit render method at some point… or a 310 status code if you don&#39;t!</p>
<p>Just keep in mind that <code>redirect_to</code> is setting the response, not triggering it, the code written after a <code>redirect_to</code> will still be executed until the function returns.</p>
<h2 id="render-uh">Render uh?</h2>
<p>As seen previously, if we want to serve our own html.erb files, we have to use <code>render</code> explicitly or not.</p>
<p>Let&#39;s use this opportunity to clear up some Rails&#39; black magic and use this very simple controller with implicit render method</p>
<pre><code class="language-ruby">class ExercicesController &lt; ApplicationController
  def index
  end
end
</code></pre>
<p>At the very beginning it comes from the Rendering helper required in <a href="https://github.com/rails/rails/blob/5-2-stable/actionpack/lib/action_controller/base.rb" rel="noopener noreferrer" target="_blank">ActionController::Base</a>. This way when<code>ActionController::Base#render</code> is called, it is actually the method located in <code>ActionView::Helpers::RenderingHelper</code>. Please have a look at the <a href="https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/helpers/rendering_helper.rb#L27" rel="noopener noreferrer" target="_blank">source code</a>.</p>
<p>From this point, there are a lot of things going on, so let&#39;s check on the steps!</p>
<h2 id="the-steps">The steps</h2>
<h3 id="actionviewhelpersrenderinghelper">ActionView::Helpers::RenderingHelper</h3>
<p>From <a href="https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/helpers/rendering_helper.rb#L27" rel="noopener noreferrer" target="_blank">this render method</a> code will decide if it must continue processing for a partial or for a template. We will here focus on templates.</p>
<pre><code class="language-ruby">def render(options = {}, locals = {}, &amp;block)
  case options
  when Hash
    if block_given?
      view_renderer.render_partial(self, options.merge(partial: options[:layout]), &amp;block)
    else
      view_renderer.render(self, options)
    end
  else
    view_renderer.render_partial(self, partial: options, locals: locals, &amp;block)
  end
end
</code></pre>
<p>But no matter if it is a template or a partial, there is always a call to a view_renderer objects method. This is step 2.</p>
<h3 id="actionviewrenderer">ActionView::Renderer</h3>
<p><a href="https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/renderer/renderer.rb#L17" target="blank" rel="noopener">Here is the render method</a> of the <code>Renderer</code> class. From the precedent function, we arrive directly to the <code>render_template</code> method line 43, but we can also pass through the <code>render</code> method wich will just determine wich method should be used, <code>render_template</code> or <code>render_partial</code>.</p>
<p>Also you can see in <code>TemplateRenderer.new(@lookup_context).render(context, options)</code> the use of the <code>@lookup_context</code> instance variable. Thats our next point.</p>
<h3 id="actionviewtemplaterenderer">ActionView::TemplateRenderer</h3>
<p><code>@lookup_context</code> as commented in the <a href="https://github.com/rails/rails/blob/master/actionview/lib/action_view/lookup_context.rb" rel="noopener noreferrer" target="_blank">source code</a> <em>&quot;is the object responsible for holding all information required for looking up templates, i.e. view paths and details&quot;</em>, and is a very complete object so take a deep breath and let&#39;s dive step by step into it by following the progression in the <code>render</code> method of the <a href="https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/renderer/template_renderer.rb" rel="noopener noreferrer" target="_blank">TemplateRenderer</a>.</p>
<pre><code class="language-ruby">class TemplateRenderer &lt; AbstractRenderer #:nodoc:
  def render(context, options)
    @view = context
    @details = extract_details(options)
    template = determine_template(options)
    prepend_formats(template.formats)

    @lookup_context.rendered_format ||= (template.formats.first || formats.first)

    render_template(template, options[:layout], options[:locals])
  end
  [...]
end
</code></pre>
<p>First of all, the TemplateRenderer as well as the <a href="https://github.com/rails/rails/blob/ed7706720e74293b310898df1bc202ae505b9731/actionview/lib/action_view/renderer/partial_renderer.rb#L285" rel="noopener noreferrer" target="_blank">PartialRenderer</a> inherits from the <a href="https://github.com/rails/rails/blob/ed7706720e74293b310898df1bc202ae505b9731/actionview/lib/action_view/renderer/abstract_renderer.rb" rel="noopener noreferrer" target="_blank">AbstractRenderer</a> and can access its methods.</p>
<p>In <code>TemplateRenderer#render</code>, @view is the context variable given in the args when we called the render method previously. @details uses <code>extract_details</code> method from <code>ActionView::AbstractRenderer</code> accessible by inheritance. Template is obtained by passing options to <code>determine_template</code>, a private method in this controller.</p>
<p>Then <code>prepend_formats</code>, another method from AbstractRenderer is given attributes <code>template.formats</code>. Then the format to render is set if not already on the <code>@lookup_context</code> object. And finally <code>render_template</code> is called</p>
<h4 id="extract_details">extract_details</h4>
<p>It&#39;s the first real encounter with <code>@lookup_context</code>. We can see in the <a href="https://github.com/rails/rails/blob/master/actionview/lib/action_view/lookup_context.rb" rel="noopener noreferrer" target="_blank">source code of the class</a> that registred_details is a module accessor.</p>
<pre><code class="language-ruby">def extract_details(options) # :doc:
  @lookup_context.registered_details.each_with_object({}) do |key, details|
    value = options[key]
    details[key] = Array(value) if value
  end
end
</code></pre>
<p>The <code>extract_details</code> method iterates on <code>@lookup_context.registered_details</code> and creates a hash of arrays filled with matching keys between options and the registred_details keys.</p>
<p>Wanna put your hands on? Just open a <code>$ rails console</code>and type in <code>$ ActionView::LookupContext.registered_details</code> to see the default values. You can also play around with <code>$ ActionView::LookupContext.fallbacks</code>.</p>
<h4 id="determine_template">determine_template</h4>
<p><a href="https://github.com/rails/rails/blob/master/actionview/lib/action_view/renderer/template_renderer.rb#L21" rel="noopener noreferrer" target="_blank">determine_template</a> is a private method checking for different keys in the options param. It looks for what kind of template it must find, and in our case it will end up passing through this condition</p>
<pre><code class="language-ruby">elsif options.key?(:template)
  if options[:template].respond_to?(:render)
    options[:template]
  else
    @lookup_context.find_template(options[:template], options[:prefixes], false, keys, @details)
end
</code></pre>
<p>At this point we dont have any template key in our options hash, we will pass in the else condition and use <a href="https://github.com/rails/rails/blob/master/actionview/lib/action_view/lookup_context.rb#L129" rel="noopener noreferrer" target="_blank">LookupContext#find_template</a> which is actually an alias of LookupContext#find.</p>
<p><code>find</code> just delegates to <code>@view_path.find</code> where <code>@view_path.find</code> == <a href="https://github.com/rails/rails/blob/ed7706720e74293b310898df1bc202ae505b9731/actionview/lib/action_view/path_set.rb#L47" rel="noopener noreferrer" target="_blank">PathSet#Find</a>.</p>
<p>There are more delegation games in this file, but finally we arrive at private method <a href="https://github.com/rails/rails/blob/ed7706720e74293b310898df1bc202ae505b9731/actionview/lib/action_view/path_set.rb#L74" rel="noopener noreferrer" target="_blank">PathSet#_Find_All</a></p>
<p><code>find_all</code> is where Rails looks for the files using <a href="https://github.com/rails/rails/blob/ed7706720e74293b310898df1bc202ae505b9731/actionview/lib/action_view/template/resolver.rb#L145">Resolver#find_all</a> in a loop.</p>
<pre><code class="language-ruby">def _find_all(path, prefixes, args, outside_app)
  prefixes = [prefixes] if String === prefixes
  prefixes.each do |prefix|
    paths.each do |resolver|
    [...]
    templates = resolver.find_all(path, prefix, *args)
    [...]
  return templates unless templates.empty
  [...]
</code></pre>
<p><code>Resolver#find_all</code> actually calls <code>PathResolver#find_templates</code>, where <code>PathResolver#query</code> is called and a new Path instance is built with path = Path.build(name, prefix, partial).</p>
<p>But you already understood a lot today (you can be poud of yourself already!) on how the templating works in RubyOnRails so take a break and come back next time for the next parts.</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails-templating-banner-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>As a web developer, my first framework ever was RubyOnRails and I still keep a particular affection among them.</p>
<p>So when the template rendering was first introduced to me, I understood how it worked on the top layers, used it and I was perfectly fine doing so, because rails’ Convention over Configuration is very powerful.</p>
<span id="more-2818"></span>

<p>But the part of me whom re coded several sys calls to understand how it works is craving to know what’s under the templates&#39; system in RoR, so let’s dive in!</p>
<p>But first of all, a warning. I’m not here to talk to you about how to use template rendering in rails, many great articles have been written on the subject already and the documentation is super explicit so if that is the reason you are here, I’d suggest you have a look <a href="https://guides.rubyonrails.org/layouts_and_rendering.html">here</a> or <a href="https://guides.rubyonrails.org/layouts_and_rendering.html#using-render">here</a>.</p>
<h2 id="how-to-trigger-template-rendering-process-">How to trigger template rendering process ?</h2>
<p>Actually there are <a href="https://evilmartians.com/chronicles/new-feature-in-rails-5-render-views-outside-of-actions" rel="noopener noreferrer" target="_blank">many fun ways</a> to trigger template rendering in Rails, but we will stick to controller here.</p>
<h3 id="1---convention-over-configuration">1 - Convention over configuration</h3>
<p>The very first thing you ever try, when you first launch a server on a <code>rails new my_project_name</code> brand-new project, is in the <a href="https://github.com/rails/rails/blob/master/railties/lib/rails/welcome_controller.rb">welcome controller</a> provided by rails. Please note the <code>layout: false</code>, we’ll get back to that later.</p>
<pre><code class="language-ruby">class Rails::WelcomeController &lt; Rails::ApplicationController # :nodoc:
  layout: false

  def index
  end
end
</code></pre>
<pre><code class="language-text">Processing by Rails::WelcomeController#index as HTML
Rendering /Users/valeriane/.rvm/gems/ruby-2.5.1/gems/railties-5.1.6.1/lib/rails/templates/rails/welcome/index.html.erb
</code></pre>
<p>As we can see the index method is empty and the rendering of <code>/rails/templates/rails/welcome/index.html.erb</code> is processed automatically. <img src="https://edgeguides.rubyonrails.org/images/getting_started/rails_welcome.png" alt="ruby on rails default home page"></p>
<h3 id="2---explicit-call-to-render-method">2 - Explicit call to render method</h3>
<pre><code class="language-ruby">  def update
    @book= Book.find(params[:id])

    if @book.update(book_params)
      redirect_to(@book)
    else
      render &quot;edit&quot;
    end
  end
</code></pre>
<p>In this <code>update</code> method, we have an explicit call to the <a href="https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/renderer/renderer.rb#L21" rel="noopener noreferrer" target="_blank">render method</a> which is actually an <a href="https://guides.rubyonrails.org/action_view_overview.html" rel="noopener noreferrer" target="_blank">ActionView</a> helper.<br>If object update fails with given params, we want the user to be able to change theses params right away. So we ask Rails to render the <code>edit</code> view instead of the <code>update</code> view it would have rendered otherwise as we are in an <code>update</code> method.</p>
<p>You can render many formats (JavaScript, JSON, plain text…) and add a ton of options, so be sure to check the <a href="https://guides.rubyonrails.org/layouts_and_rendering.html#using-render" rel="noopener noreferrer" target="_blank">full documentation</a>.</p>
<h3 id="3---rendering-html-headers-only">3 - Rendering HTML headers only</h3>
<pre><code class="language-ruby">def show
  if !params[:id]
    head :bad_request
  else
    @book = Book.find(params[:id])
  end
end
</code></pre>
<p><a href="https://apidock.com/rails/v4.2.7/ActionController/Head/head" rel="noopener noreferrer" target="_blank">head method</a> is used to send specific headers only responses to the browser. Here the <code>:bad_request</code> symbol represents the 400 HTTP code. This usage is not suitable for production.<br>As this is not using the template rendering process we won&#39;t discuss <code>head</code> further here.</p>
<h3 id="4---hey-there-was-a-redirect_to-in-example-2">4 - Hey, there was a redirect_to in example 2!</h3>
<p>You are absolutely right.<br><code>redirect_to</code> is a method that sets the response by default to 302 HTTP code and adds default instructions to tell browsers which request to build next.<br>As for render there is a large list of options you can provide, <a href="https://api.rubyonrails.org/classes/ActionController/Redirecting.html#method-i-redirect_to" rel="noopener noreferrer" target="_blank">read the docs</a>!</p>
<p>Once this instruction is sent to the browser, nothing will happen until the server receives the new request built by the browser. At this point, the process of handling request will restart from the beginning and even if there is a new <code>redirect_to</code> in your way you will fatally end up encountering a head method, an implicit or an explicit render method at some point… or a 310 status code if you don&#39;t!</p>
<p>Just keep in mind that <code>redirect_to</code> is setting the response, not triggering it, the code written after a <code>redirect_to</code> will still be executed until the function returns.</p>
<h2 id="render-uh">Render uh?</h2>
<p>As seen previously, if we want to serve our own html.erb files, we have to use <code>render</code> explicitly or not.</p>
<p>Let&#39;s use this opportunity to clear up some Rails&#39; black magic and use this very simple controller with implicit render method</p>
<pre><code class="language-ruby">class ExercicesController &lt; ApplicationController
  def index
  end
end
</code></pre>
<p>At the very beginning it comes from the Rendering helper required in <a href="https://github.com/rails/rails/blob/5-2-stable/actionpack/lib/action_controller/base.rb" rel="noopener noreferrer" target="_blank">ActionController::Base</a>. This way when<code>ActionController::Base#render</code> is called, it is actually the method located in <code>ActionView::Helpers::RenderingHelper</code>. Please have a look at the <a href="https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/helpers/rendering_helper.rb#L27" rel="noopener noreferrer" target="_blank">source code</a>.</p>
<p>From this point, there are a lot of things going on, so let&#39;s check on the steps!</p>
<h2 id="the-steps">The steps</h2>
<h3 id="actionviewhelpersrenderinghelper">ActionView::Helpers::RenderingHelper</h3>
<p>From <a href="https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/helpers/rendering_helper.rb#L27" rel="noopener noreferrer" target="_blank">this render method</a> code will decide if it must continue processing for a partial or for a template. We will here focus on templates.</p>
<pre><code class="language-ruby">def render(options = {}, locals = {}, &amp;block)
  case options
  when Hash
    if block_given?
      view_renderer.render_partial(self, options.merge(partial: options[:layout]), &amp;block)
    else
      view_renderer.render(self, options)
    end
  else
    view_renderer.render_partial(self, partial: options, locals: locals, &amp;block)
  end
end
</code></pre>
<p>But no matter if it is a template or a partial, there is always a call to a view_renderer objects method. This is step 2.</p>
<h3 id="actionviewrenderer">ActionView::Renderer</h3>
<p><a href="https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/renderer/renderer.rb#L17" target="blank" rel="noopener">Here is the render method</a> of the <code>Renderer</code> class. From the precedent function, we arrive directly to the <code>render_template</code> method line 43, but we can also pass through the <code>render</code> method wich will just determine wich method should be used, <code>render_template</code> or <code>render_partial</code>.</p>
<p>Also you can see in <code>TemplateRenderer.new(@lookup_context).render(context, options)</code> the use of the <code>@lookup_context</code> instance variable. Thats our next point.</p>
<h3 id="actionviewtemplaterenderer">ActionView::TemplateRenderer</h3>
<p><code>@lookup_context</code> as commented in the <a href="https://github.com/rails/rails/blob/master/actionview/lib/action_view/lookup_context.rb" rel="noopener noreferrer" target="_blank">source code</a> <em>&quot;is the object responsible for holding all information required for looking up templates, i.e. view paths and details&quot;</em>, and is a very complete object so take a deep breath and let&#39;s dive step by step into it by following the progression in the <code>render</code> method of the <a href="https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/renderer/template_renderer.rb" rel="noopener noreferrer" target="_blank">TemplateRenderer</a>.</p>
<pre><code class="language-ruby">class TemplateRenderer &lt; AbstractRenderer #:nodoc:
  def render(context, options)
    @view = context
    @details = extract_details(options)
    template = determine_template(options)
    prepend_formats(template.formats)

    @lookup_context.rendered_format ||= (template.formats.first || formats.first)

    render_template(template, options[:layout], options[:locals])
  end
  [...]
end
</code></pre>
<p>First of all, the TemplateRenderer as well as the <a href="https://github.com/rails/rails/blob/ed7706720e74293b310898df1bc202ae505b9731/actionview/lib/action_view/renderer/partial_renderer.rb#L285" rel="noopener noreferrer" target="_blank">PartialRenderer</a> inherits from the <a href="https://github.com/rails/rails/blob/ed7706720e74293b310898df1bc202ae505b9731/actionview/lib/action_view/renderer/abstract_renderer.rb" rel="noopener noreferrer" target="_blank">AbstractRenderer</a> and can access its methods.</p>
<p>In <code>TemplateRenderer#render</code>, @view is the context variable given in the args when we called the render method previously. @details uses <code>extract_details</code> method from <code>ActionView::AbstractRenderer</code> accessible by inheritance. Template is obtained by passing options to <code>determine_template</code>, a private method in this controller.</p>
<p>Then <code>prepend_formats</code>, another method from AbstractRenderer is given attributes <code>template.formats</code>. Then the format to render is set if not already on the <code>@lookup_context</code> object. And finally <code>render_template</code> is called</p>
<h4 id="extract_details">extract_details</h4>
<p>It&#39;s the first real encounter with <code>@lookup_context</code>. We can see in the <a href="https://github.com/rails/rails/blob/master/actionview/lib/action_view/lookup_context.rb" rel="noopener noreferrer" target="_blank">source code of the class</a> that registred_details is a module accessor.</p>
<pre><code class="language-ruby">def extract_details(options) # :doc:
  @lookup_context.registered_details.each_with_object({}) do |key, details|
    value = options[key]
    details[key] = Array(value) if value
  end
end
</code></pre>
<p>The <code>extract_details</code> method iterates on <code>@lookup_context.registered_details</code> and creates a hash of arrays filled with matching keys between options and the registred_details keys.</p>
<p>Wanna put your hands on? Just open a <code>$ rails console</code>and type in <code>$ ActionView::LookupContext.registered_details</code> to see the default values. You can also play around with <code>$ ActionView::LookupContext.fallbacks</code>.</p>
<h4 id="determine_template">determine_template</h4>
<p><a href="https://github.com/rails/rails/blob/master/actionview/lib/action_view/renderer/template_renderer.rb#L21" rel="noopener noreferrer" target="_blank">determine_template</a> is a private method checking for different keys in the options param. It looks for what kind of template it must find, and in our case it will end up passing through this condition</p>
<pre><code class="language-ruby">elsif options.key?(:template)
  if options[:template].respond_to?(:render)
    options[:template]
  else
    @lookup_context.find_template(options[:template], options[:prefixes], false, keys, @details)
end
</code></pre>
<p>At this point we dont have any template key in our options hash, we will pass in the else condition and use <a href="https://github.com/rails/rails/blob/master/actionview/lib/action_view/lookup_context.rb#L129" rel="noopener noreferrer" target="_blank">LookupContext#find_template</a> which is actually an alias of LookupContext#find.</p>
<p><code>find</code> just delegates to <code>@view_path.find</code> where <code>@view_path.find</code> == <a href="https://github.com/rails/rails/blob/ed7706720e74293b310898df1bc202ae505b9731/actionview/lib/action_view/path_set.rb#L47" rel="noopener noreferrer" target="_blank">PathSet#Find</a>.</p>
<p>There are more delegation games in this file, but finally we arrive at private method <a href="https://github.com/rails/rails/blob/ed7706720e74293b310898df1bc202ae505b9731/actionview/lib/action_view/path_set.rb#L74" rel="noopener noreferrer" target="_blank">PathSet#_Find_All</a></p>
<p><code>find_all</code> is where Rails looks for the files using <a href="https://github.com/rails/rails/blob/ed7706720e74293b310898df1bc202ae505b9731/actionview/lib/action_view/template/resolver.rb#L145">Resolver#find_all</a> in a loop.</p>
<pre><code class="language-ruby">def _find_all(path, prefixes, args, outside_app)
  prefixes = [prefixes] if String === prefixes
  prefixes.each do |prefix|
    paths.each do |resolver|
    [...]
    templates = resolver.find_all(path, prefix, *args)
    [...]
  return templates unless templates.empty
  [...]
</code></pre>
<p><code>Resolver#find_all</code> actually calls <code>PathResolver#find_templates</code>, where <code>PathResolver#query</code> is called and a new Path instance is built with path = Path.build(name, prefix, partial).</p>
<p>But you already understood a lot today (you can be poud of yourself already!) on how the templating works in RubyOnRails so take a break and come back next time for the next parts.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
