<?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>framework Archives | Clever Cloud</title>
	<atom:link href="https://stagingv6.cleverapps.io/blog/tag/framework/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>From Code to Product</description>
	<lastBuildDate>Tue, 09 Jun 2020 10:40: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>framework Archives | Clever Cloud</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>How to Deploy your Elixir/Phoenix Application to Production</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2020/06/09/deploy-elixir-phoenix/</link>
		
		<dc:creator><![CDATA[Valeriane Venance]]></dc:creator>
		<pubDate>Tue, 09 Jun 2020 10:40:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[elixir]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[phoenix]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2020/06/09/deploy-elixir-phoenix/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/phoenix-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/phoenix-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/phoenix-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/phoenix-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/phoenix-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/phoenix-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p>Hi everyone! Today let's follow a simple deployment tutorial to learn how to deploy your Elixir/Phoenix Application.

<span id="more-2828"></span>
<h2 id="step-1-creating-a-new-phoenix-application">Step 1: Creating a new Phoenix Application</h2>
If you follow this tutorial, I assume you already have Elixir and Phoenix's dependencies installed locally. If you don't, you will probably want to read <a href="https://hexdocs.pm/phoenix/installation.html">this tutorial</a>.

To create a brand-new Phoenix application locally, we just need to type in our terminal:
<pre><code class="language-bash">$ mix phx.new &lt;your application's name&gt; # creating the new phoenix project
$ cd &lt;your application's name&gt;
$ mix ecto.create # creating database locally
</code></pre>
Creating the database locally isn't crucial for this tutorial, but it can help if you want to code on your machine.
<h3 id="note-to-osx-users">Note to OSX users</h3>
If you use OSX like me, you may encounter this error: <code>(Postgrex.Error) FATAL 28000 (invalid_authorization_specification) role "postgres" does not exist</code>. This is because when installing PostgreSQL with brew, it creates a user with your short name, not <code>postgres</code>. To fix this, open the project with your favorite text editor and replace <code>username: "postgres",</code> by <code>username: "&lt;your name&gt;",</code> in the file <code>config/dev.exs</code>. For instance, my name is <code>valeriane venance</code> in my computer so I replace with <code>username: "valeriane",</code>.
<h2 id="step-2-getting-our-application-ready-for-production">Step 2: Getting your Application Ready for Production</h2>
From the code perspective, all we need to do is to edit <code>config/prod.secret.exs</code> to replace <code>System.get_env("DATABASE_URL")</code> with <code>System.get_env("POSTGRESQL_ADDON_URI")</code>. This is because we will use the PostgreSQL add-on environment variable provided by Clever Cloud to your application instead of the default value.

Back in our terminal, we will generate a secret token that we will save for later with <code>$ mix phx.gen.secret</code> and check our elixir version with <code>$ elixir -v</code>.

And that's it. Easy right? Now let's go into our <a href="https://console.clever-cloud.com" target="_blank" rel="noopener">Clever Cloud console</a>.
<h2 id="step-3-creating-the-prod-application-and-database">Step 3: Creating the Prod Application and Database</h2>
If you already are a Clever Cloud user, these steps must be really familiar to you:
<ul>
 	<li>Under the organization of your choice, click new, then application. Select <strong>Elixir</strong>, then name your application and choose its deployment zone.</li>
 	<li>When prompted if you need an add-on, select <strong>PostgreSQL</strong>. Select your database size and name it.</li>
 	<li>On the environment variable screen create two new ones:</li>
 	<li><strong>SECRET_KEY_BASE</strong> with the value obtained from <code>$ mix phx.gen.secret</code> previously</li>
 	<li><strong>CC_ELIXIR_VERSION</strong> with the value of <code>$ elixir -v</code> result. (Available values as of today are <code>1.8</code>, <code>1.9</code> or <code>1.10</code>)</li>
 	<li>Click on <strong>update changes</strong></li>
 	<li>Bonus: if you have migrations to run you could also set the environment variable <strong>CC_PHOENIX_RUN_ECTO_MIGRATE</strong> to <code>true</code> to trigger the command <code>$ mix ecto.migrate</code></li>
</ul>
<h2 id="step-4-deploy">Step 4: deploy!</h2>
Once the previous steps are made, Clever Cloud will provide you a git remote and the commands to add the remote and to push your code. If you had not done it before, initialize a new git repository in your terminal with <code>git init</code>. Then add and commit your code. Now you should be able to copy and paste the provided git commands. If you go back to your Clever Cloud console, you will see that your deployment has started and logs should show up. Wait a few moments and your application will be up and running. You can visit it by clicking the link icon on top of your application's menu in the Clever Cloud console.
<h2 id="the-magic-explained">The magic explained</h2>
As Phoenix is a framework that was built to be as easy to use as RubyOnRails but less <em>magical</em>, let's demystify what just happened here.

When we push our code to the remote Clever Cloud provided, the following commands are run:
<pre><code class="language-bash">$ mix deps.get
$ mix deps.compile
$ npm install
</code></pre>
These commands will compile your dependencies at the root of your project folder. If you want to use another folder for <code>npm install</code>, specify it via the environment variable <strong>CC_PHOENIX_ASSETS_DIR</strong>. To change the folder for the entire build/run process, you should use the <strong>APP_FOLDER</strong> environment variable.

Then <code>$ mix compile</code> is run. If you want to override this behavior, you can set the environment variable <strong>CC_MIX_BUILD_GOAL</strong> to the value you desire.

At this point, there is the command <code>$ npm run deploy</code>.

Then <code>$ mix phx.digest</code> is run. You can override this one with the variable <strong>CC_PHOENIX_DIGEST_GOAL</strong>.

Finally, <code>$ mix phx.server</code> is invoked, and as always, you can override this behavior, either with <strong>CC_RUN_COMMAND</strong> where you have to specify the full command, or <strong>CC_PHOENIX_SERVER_GOAL</strong> where it will be a mix task by default.

If you need to specify the time zone of your application, you can do it with the variable <strong>TZ</strong> set to the usual time zone format, for instance <code>Europe/Paris</code>.

And that's it really, now you know how to deploy your Elixir/Phoenix Application. All you have to do left is write code, commit and push it again! Happy hacking!]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/phoenix-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/phoenix-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/phoenix-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/phoenix-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/phoenix-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/phoenix-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p>Hi everyone! Today let's follow a simple deployment tutorial to learn how to deploy your Elixir/Phoenix Application.

<span id="more-2828"></span>
<h2 id="step-1-creating-a-new-phoenix-application">Step 1: Creating a new Phoenix Application</h2>
If you follow this tutorial, I assume you already have Elixir and Phoenix's dependencies installed locally. If you don't, you will probably want to read <a href="https://hexdocs.pm/phoenix/installation.html">this tutorial</a>.

To create a brand-new Phoenix application locally, we just need to type in our terminal:
<pre><code class="language-bash">$ mix phx.new &lt;your application's name&gt; # creating the new phoenix project
$ cd &lt;your application's name&gt;
$ mix ecto.create # creating database locally
</code></pre>
Creating the database locally isn't crucial for this tutorial, but it can help if you want to code on your machine.
<h3 id="note-to-osx-users">Note to OSX users</h3>
If you use OSX like me, you may encounter this error: <code>(Postgrex.Error) FATAL 28000 (invalid_authorization_specification) role "postgres" does not exist</code>. This is because when installing PostgreSQL with brew, it creates a user with your short name, not <code>postgres</code>. To fix this, open the project with your favorite text editor and replace <code>username: "postgres",</code> by <code>username: "&lt;your name&gt;",</code> in the file <code>config/dev.exs</code>. For instance, my name is <code>valeriane venance</code> in my computer so I replace with <code>username: "valeriane",</code>.
<h2 id="step-2-getting-our-application-ready-for-production">Step 2: Getting your Application Ready for Production</h2>
From the code perspective, all we need to do is to edit <code>config/prod.secret.exs</code> to replace <code>System.get_env("DATABASE_URL")</code> with <code>System.get_env("POSTGRESQL_ADDON_URI")</code>. This is because we will use the PostgreSQL add-on environment variable provided by Clever Cloud to your application instead of the default value.

Back in our terminal, we will generate a secret token that we will save for later with <code>$ mix phx.gen.secret</code> and check our elixir version with <code>$ elixir -v</code>.

And that's it. Easy right? Now let's go into our <a href="https://console.clever-cloud.com" target="_blank" rel="noopener">Clever Cloud console</a>.
<h2 id="step-3-creating-the-prod-application-and-database">Step 3: Creating the Prod Application and Database</h2>
If you already are a Clever Cloud user, these steps must be really familiar to you:
<ul>
 	<li>Under the organization of your choice, click new, then application. Select <strong>Elixir</strong>, then name your application and choose its deployment zone.</li>
 	<li>When prompted if you need an add-on, select <strong>PostgreSQL</strong>. Select your database size and name it.</li>
 	<li>On the environment variable screen create two new ones:</li>
 	<li><strong>SECRET_KEY_BASE</strong> with the value obtained from <code>$ mix phx.gen.secret</code> previously</li>
 	<li><strong>CC_ELIXIR_VERSION</strong> with the value of <code>$ elixir -v</code> result. (Available values as of today are <code>1.8</code>, <code>1.9</code> or <code>1.10</code>)</li>
 	<li>Click on <strong>update changes</strong></li>
 	<li>Bonus: if you have migrations to run you could also set the environment variable <strong>CC_PHOENIX_RUN_ECTO_MIGRATE</strong> to <code>true</code> to trigger the command <code>$ mix ecto.migrate</code></li>
</ul>
<h2 id="step-4-deploy">Step 4: deploy!</h2>
Once the previous steps are made, Clever Cloud will provide you a git remote and the commands to add the remote and to push your code. If you had not done it before, initialize a new git repository in your terminal with <code>git init</code>. Then add and commit your code. Now you should be able to copy and paste the provided git commands. If you go back to your Clever Cloud console, you will see that your deployment has started and logs should show up. Wait a few moments and your application will be up and running. You can visit it by clicking the link icon on top of your application's menu in the Clever Cloud console.
<h2 id="the-magic-explained">The magic explained</h2>
As Phoenix is a framework that was built to be as easy to use as RubyOnRails but less <em>magical</em>, let's demystify what just happened here.

When we push our code to the remote Clever Cloud provided, the following commands are run:
<pre><code class="language-bash">$ mix deps.get
$ mix deps.compile
$ npm install
</code></pre>
These commands will compile your dependencies at the root of your project folder. If you want to use another folder for <code>npm install</code>, specify it via the environment variable <strong>CC_PHOENIX_ASSETS_DIR</strong>. To change the folder for the entire build/run process, you should use the <strong>APP_FOLDER</strong> environment variable.

Then <code>$ mix compile</code> is run. If you want to override this behavior, you can set the environment variable <strong>CC_MIX_BUILD_GOAL</strong> to the value you desire.

At this point, there is the command <code>$ npm run deploy</code>.

Then <code>$ mix phx.digest</code> is run. You can override this one with the variable <strong>CC_PHOENIX_DIGEST_GOAL</strong>.

Finally, <code>$ mix phx.server</code> is invoked, and as always, you can override this behavior, either with <strong>CC_RUN_COMMAND</strong> where you have to specify the full command, or <strong>CC_PHOENIX_SERVER_GOAL</strong> where it will be a mix task by default.

If you need to specify the time zone of your application, you can do it with the variable <strong>TZ</strong> set to the usual time zone format, for instance <code>Europe/Paris</code>.

And that's it really, now you know how to deploy your Elixir/Phoenix Application. All you have to do left is write code, commit and push it again! Happy hacking!]]></content:encoded>
					
		
		
			</item>
		<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" 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" loading="lazy" 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="auto, (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>
