<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Fernando Shayani</title>
    <description>The latest articles on DEV Community by Fernando Shayani (@shayani).</description>
    <link>https://dev.to/shayani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F540815%2F219a07bf-b54f-4681-ad96-e8805882ee45.png</url>
      <title>DEV Community: Fernando Shayani</title>
      <link>https://dev.to/shayani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shayani"/>
    <language>en</language>
    <item>
      <title>Run RSpec tests on changed files only</title>
      <dc:creator>Fernando Shayani</dc:creator>
      <pubDate>Fri, 29 Mar 2024 19:29:23 +0000</pubDate>
      <link>https://dev.to/shayani/run-rspec-tests-on-changed-files-only-471m</link>
      <guid>https://dev.to/shayani/run-rspec-tests-on-changed-files-only-471m</guid>
      <description>&lt;p&gt;I always do my best to run tests on my local machine before publishing a PR. However, depending on the size of the test base, this could be unsustainable.&lt;/p&gt;

&lt;p&gt;To solve this, I at least run the tests on all &lt;code&gt;*_spec.rb&lt;/code&gt; files of my current working branch (or stack of branches) that were changed (or created) since another branch. Usually, it’s main or staging.&lt;/p&gt;

&lt;p&gt;Let’s look at the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;o feature-2/more-features
|   changed file: user_spec.rb
o bugfix/fix-users-controller-params
|   created file: users_controller_spec.rb
o feature-1/branch-1-new-feature
|   updated file: product_spec.rb
|   updated file: new_payment_service_spec.rb
o main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This is a purely didactic example&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This stack of branches has changed/created 4 spec files. Now, I want to run RSpec on only those four files, not on the entire test base.&lt;/p&gt;

&lt;p&gt;To achieve this goal, I created a bash script to use git to list all changed &lt;code&gt;*_spec.rb&lt;/code&gt; files and run the &lt;code&gt;rspec&lt;/code&gt; command against them. Here is the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# Set default branch name&lt;/span&gt;
&lt;span class="nv"&gt;branch_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;staging&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Get changed files with grep for _spec.rb extension&lt;/span&gt;
&lt;span class="nv"&gt;changed_specs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git diff &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;--diff-filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;d &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;_spec.rb&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Check if any changed specs found&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$changed_specs&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No changed _spec.rb files found between HEAD and &lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"List of changed spec files:"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$changed_specs&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Run rspec with all changed specs&lt;/span&gt;
bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rspec &lt;span class="nv"&gt;$changed_specs&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"RSpec tests completed for changed _spec.rb files."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;a href="https://gist.github.com/shayani/c4fd6c427f932ab9fe3e98185a912e61"&gt;Click here to view and download this gist&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Save this file and give it a name (I use &lt;code&gt;rspec_changed_files.sh&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;Now, simply run it on your repo directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./rspec_changed_files.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, it will find the changed files related to the &lt;code&gt;staging&lt;/code&gt; branch, but you can adapt the code or override the branch on the command line with another branch name or commit hash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./rspec_changed_files.sh main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;List of changed spec files:
spec/models/user_spec.rb
spec/controllers/users_controller_spec.rb
spec/models/product_spec.rb
spec/services/new_payment_service_spec.rb
....................

Finished &lt;span class="k"&gt;in &lt;/span&gt;0.60517 seconds &lt;span class="o"&gt;(&lt;/span&gt;files took 1.81 seconds to load&lt;span class="o"&gt;)&lt;/span&gt;
10 examples, 0 failures

RSpec tests completed &lt;span class="k"&gt;for &lt;/span&gt;changed _spec.rb files.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Happy testing!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>rspec</category>
      <category>testing</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Ignoring a Rails model attribute</title>
      <dc:creator>Fernando Shayani</dc:creator>
      <pubDate>Sat, 16 Mar 2024 10:37:49 +0000</pubDate>
      <link>https://dev.to/shayani/ignoring-a-rails-model-attribute-3d5i</link>
      <guid>https://dev.to/shayani/ignoring-a-rails-model-attribute-3d5i</guid>
      <description>&lt;p&gt;Imagine that you need to remove an obsolete field from your production database, but you're not confident that this field is truly unused. How can you proceed safely? If only there were a way to pretend that this field no longer exists, allowing you to check if the application still functions properly without it.&lt;/p&gt;

&lt;p&gt;Enter &lt;code&gt;ActiveRecord&lt;/code&gt;'s &lt;code&gt;ignored_columns&lt;/code&gt; to the rescue!&lt;/p&gt;

&lt;p&gt;With this feature, you can instruct ActiveRecord to behave as if a specific database field doesn't exist. It removes all accessors related to that field from the model and ignores it in database queries.&lt;/p&gt;

&lt;p&gt;Let's take a look at an example:&lt;/p&gt;

&lt;p&gt;Suppose you have a model called &lt;code&gt;Person&lt;/code&gt; with several attributes, and you want to eliminate the &lt;code&gt;middle_name&lt;/code&gt; field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="c1"&gt;# Schema:&lt;/span&gt;
  &lt;span class="c1"&gt;#   id          :bigint&lt;/span&gt;
  &lt;span class="c1"&gt;#   first_name  :string, limit: 255&lt;/span&gt;
  &lt;span class="c1"&gt;#   middle_name :string, limit: 255&lt;/span&gt;
  &lt;span class="c1"&gt;#   last_name   :string, limit: 255&lt;/span&gt;
  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ignored_columns&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:middle_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comes ActiveRecord&lt;code&gt;ignored_columns&lt;/code&gt; for the rescue! &lt;/p&gt;

&lt;p&gt;With it, you can instruct ActiveRecord to pretend that a specific database field doesn't exist, removing all accessors from the model and ignoring the field on database queries.&lt;/p&gt;

&lt;p&gt;Let's see an example:&lt;/p&gt;

&lt;p&gt;You have the model &lt;code&gt;Person&lt;/code&gt; with some attributes and you want to get rid of &lt;code&gt;middle_name&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="c1"&gt;# schema:&lt;/span&gt;
  &lt;span class="c1"&gt;#   id          :bigint&lt;/span&gt;
  &lt;span class="c1"&gt;#   first_name  :string, limit: 255&lt;/span&gt;
  &lt;span class="c1"&gt;#   middle_name :string, limit: 255&lt;/span&gt;
  &lt;span class="c1"&gt;#   last_name   :string, limit: 255&lt;/span&gt;
  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ignored_columns&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:middle_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, any attempts to access the &lt;code&gt;middle_name&lt;/code&gt; attribute will fail. For instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;first_name: &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;middle_name&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; raises NoMethodError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Attention:&lt;/strong&gt; Keep in mind that this approach won’t prevent direct database calls to fetch this field. The field itself hasn’t been removed from the database; it’s simply ignored by ActiveRecord.&lt;/p&gt;

&lt;p&gt;Once you’ve thoroughly tested your application and verified that everything works as expected, you can create a new migration to permanently remove the field from the database.&lt;/p&gt;

&lt;p&gt;Happy coding! 😊&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://apidock.com/rails/v7.1.3.2/ActiveRecord/ModelSchema/ClassMethods/ignored_columns%3D"&gt;ActiveRecord &lt;code&gt;ignored_columns&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>database</category>
    </item>
    <item>
      <title>Dockerizing a Rails application for production deployment</title>
      <dc:creator>Fernando Shayani</dc:creator>
      <pubDate>Mon, 29 Aug 2022 12:13:00 +0000</pubDate>
      <link>https://dev.to/shayani/dockerizing-a-rails-application-for-production-deployment-2elc</link>
      <guid>https://dev.to/shayani/dockerizing-a-rails-application-for-production-deployment-2elc</guid>
      <description>&lt;p&gt;After many years using manual tools to deploy my Ruby on Rails applications, I changed my production deployment strategy to use Docker containers few years ago, and it was a great decision!&lt;/p&gt;

&lt;p&gt;This tutorial is for begginers that want to dockerize their new (or existing) Rails application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt;ℹ️ You can download all files on &lt;a href="https://github.com/shayani/dockerizing_rails_app" rel="noopener noreferrer"&gt;my Github repository&lt;/a&gt;.&lt;br&gt;
&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Why dockerize my Rails application?&lt;/li&gt;
&lt;li&gt;
Starting with a basic Rails application

&lt;ul&gt;
&lt;li&gt;The setup&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Let's start!

&lt;ul&gt;
&lt;li&gt;The config/database.yml file&lt;/li&gt;
&lt;li&gt;The Dockerfile&lt;/li&gt;
&lt;li&gt;The .dockerignore&lt;/li&gt;
&lt;li&gt;Building the container&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Going production!

&lt;ul&gt;
&lt;li&gt;The Docker Compose file&lt;/li&gt;
&lt;li&gt;Starting up our application&lt;/li&gt;
&lt;li&gt;Acessing the Rails console&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Updating the containers&lt;/li&gt;

&lt;li&gt;Configure your web server&lt;/li&gt;

&lt;li&gt;Final tip!&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why dockerize my Rails application? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Turn you Rails application into docker containers for production deployment can speed up your deployment, prevent errors and make it much easier to move from one service provider to another. It made my life easier (and I bet it can make yours too!).&lt;/p&gt;

&lt;p&gt;Once in a container, all dependencies will always be installed and the system already configured to run an optimized version of you application.&lt;/p&gt;

&lt;p&gt;It's also easy to update your container, run tests, use CI/CD and automatically deploy new version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting with a basic Rails application &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;For demonstration purposes, this Rails application is a simple contact list running Rails 6.1. The user can add, view, edit and delete records from the database. All records are saved on a local PostgreSQL instance.&lt;/p&gt;

&lt;h3&gt;
  
  
  The setup &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Everything is setup on the local machine. Rails connects to PostgreSQL through port 5432 and serves the application to browsers through port 3000.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqygntibgo44f700ylsvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqygntibgo44f700ylsvt.png" alt="Localmachine diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To follow this tutorial, I assume you already have your Rails application working and running. If not, you can use &lt;a href="https://github.com/shayani/dockerizing_rails_app" rel="noopener noreferrer"&gt;the tutorial application&lt;/a&gt; for your tests.&lt;/p&gt;

&lt;p&gt;Follows a screenshot of the application running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2e949aqahdzbr6q3fe2q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2e949aqahdzbr6q3fe2q.png" alt="Application screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's start! &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There are few steps to build a container to run our application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adjust your database connection configuration.&lt;/li&gt;
&lt;li&gt;Write a &lt;code&gt;dockerfile&lt;/code&gt; and build the container.&lt;/li&gt;
&lt;li&gt;Upload your container to any could provider (free and optional).&lt;/li&gt;
&lt;li&gt;Write a Docker Compose file to execute your application on production.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;config/database.yml&lt;/code&gt; file &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is the basic Rails configuration to connect the application to the datbase. It assumes there's a local instance of PostgreSQL running with username and password configured as below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;default&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgresql&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5432&lt;/span&gt;
  &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
  &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;

&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;devel_db&lt;/span&gt;

&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test_db&lt;/span&gt;

&lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production_db&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see, all database connection configuration is fixed to the current environment. This can work for local environments, but as a good practice &lt;strong&gt;we should change them to environment variables&lt;/strong&gt;, so we can adjust easily for any new environment we publish our app.&lt;/p&gt;

&lt;p&gt;Let's change &lt;code&gt;host&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; for now. The others settings can also be changed, but I don't want this tutorial to be too complex 😉&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['DB_HOST'] || 'localhost' %&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['DB_USERNAME'] || 'postgres' %&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['DB_PASSWORD'] || 'postgres' %&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt;⚠️ Notice that we set default values for everything.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;Dockerfile&lt;/code&gt; &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The next step is create a file called &lt;code&gt;Dockerfile&lt;/code&gt; on the root path of your application. This file will instruct docker on how to build the application based on a image you choose.&lt;/p&gt;

&lt;p&gt;I decided to use the image &lt;code&gt;ruby:2.7.6-bullseye&lt;/code&gt; because it's based on Debian 11 (Bullseye) and I like (and I'm used to) this distribuition.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ruby:2.7.6&lt;/span&gt;

&lt;span class="c"&gt;# Directory where the app will be installed on the container&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Install NodeJS 14 repository&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://deb.nodesource.com/setup_14.x | bash -

&lt;span class="c"&gt;# Update the system and install NodeJS&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  nodejs &lt;span class="se"&gt;\
&lt;/span&gt;  vim &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="c"&gt;# Install ruby gems&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; Gemfile Gemfile.lock ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;bundle &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Install Yarn globally&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; yarn

&lt;span class="c"&gt;# Run `yarn install`&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json yarn.lock ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Copy the application file to the container&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Pre-compile assets for production&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nv"&gt;RAILS_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rails assets:precompile

&lt;span class="c"&gt;# Sets the default command that will run when the container starts&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt;ℹ️ More information of &lt;code&gt;Dockerfile&lt;/code&gt; can be found &lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;on this link&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;.dockerignore&lt;/code&gt; file &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;There are files and folders that we do not want to be copied to our docker container because they are not relevant to the application or they will be generated when the container is created. They are build folders, temporary files, log, etc.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.dockerignore&lt;/code&gt; file on your project root folder and add these lines:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

node_modules/
log/
tmp/


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Building the container &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now it's time to build our application container.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt;⚠️ &lt;strong&gt;IMPORTANT:&lt;/strong&gt; The &lt;code&gt;tag&lt;/code&gt; attribute is the name of the container. Be sure to change it to your Doker Hub repository name, or use any name if you do not intent to push it to a cloud. &lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--tag&lt;/span&gt; fshayani/dockerizing_rails_application:latest


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After the container is built successfully, we will upload it to Docker Hub. This way I can download it automatically on my production server.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt;ℹ️ This is a optional step. You can skip this step if you intent to build the container and use it on the same machine. &lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker push fshayani/dockerizing_rails_application:latest


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Going production! &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we have built our app container (and maybe pushed it to a cloud; did you?), it's time to move to the production server and deploy that application!&lt;/p&gt;

&lt;p&gt;We need tell Docker how to pull and start the container and this can be done easly with &lt;code&gt;docker compose&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt;ℹ️ There are others technologies to deploy containers in production instead of Docker Compose, like Kubernetes, Docker Swarm, AWS ECS, etc; but that's not the scope of this tutorial.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  The Docker Compose file &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;docker-compose.yml&lt;/code&gt; file on production server. It can be placed anywhere, but be organized! 😉&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# That's the name of our application container&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fshayani/dockerizing_rails_application:latest&lt;/span&gt; &lt;span class="c1"&gt;# The container Docker will use&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;3000:3000&lt;/span&gt; &lt;span class="c1"&gt;# Map localhost:3000 to the container's port 3000&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DB_HOST=db&lt;/span&gt; &lt;span class="c1"&gt;# The name of our PostgreSQL container&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DB_USERNAME=postgres&lt;/span&gt; &lt;span class="c1"&gt;# PostgreSQL credentials&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DB_PASSWORD=postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;RAILS_ENV=production&lt;/span&gt; &lt;span class="c1"&gt;# We are on Production now!&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;RAILS_SERVE_STATIC_FILES=true&lt;/span&gt; &lt;span class="c1"&gt;# Assets were already built by Dockerfile ;)&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;RAILS_LOG_TO_STDOUT=true&lt;/span&gt; &lt;span class="c1"&gt;# So we can see Rails logs with `docker compose logs` command&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;RAILS_MASTER_KEY=my_ultra_top_secret_master_key!!&lt;/span&gt; &lt;span class="c1"&gt;# Use you master key. There are better ways to keep this secret.&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt; &lt;span class="c1"&gt;# Will start the container `db` before&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:14&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=postgres&lt;/span&gt; &lt;span class="c1"&gt;# Will create a instance of PostgreSQL with this credentials&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=postgres&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres:/var/lib/postgresql/data&lt;/span&gt; &lt;span class="c1"&gt;# Map PostgreSQL data to a persistant volume called `postgres`&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Create a persistant volume on local machine, so we do not loose our DB on restarts&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Starting up our application &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now that everything is ready, let's start our application on the production server!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt;⚠️ &lt;strong&gt;ATTENTION:&lt;/strong&gt; If that's our first time to run the application on the server,&lt;br&gt;
probably your database will be empty. You have two options: &lt;code&gt;dump&lt;/code&gt; and &lt;code&gt;restore&lt;/code&gt;&lt;br&gt;
your database on the &lt;code&gt;db&lt;/code&gt; container or create a new from scratch running this command first:&lt;br&gt;
&lt;code&gt;docker compose run --rm app bundle exec rails db:setup&lt;/code&gt;&lt;br&gt;
&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker compose up


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and open your browser on &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; 😄 You will see your application running!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt;ℹ️ &lt;strong&gt;TIP:&lt;/strong&gt; Add the flag &lt;code&gt;-d&lt;/code&gt; to the command to run it on the background.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Accessing Rails console &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;With Docker Compose, we can interact with our container and run any command on it (including &lt;code&gt;bash&lt;/code&gt; if necessary).&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;docker compose &lt;span class="nb"&gt;exec &lt;/span&gt;app bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rails console&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Updating the containers &lt;a&gt;&lt;/a&gt;&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;When you make a new version of your application and want to deploy it to the production, all you need to do is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build the new image.&lt;/li&gt;
&lt;li&gt;Push it to the cloud again.&lt;/li&gt;
&lt;li&gt;Pull it on the production server the production server (&lt;code&gt;docker compose pull&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Rebuild your docker compose stack (&lt;code&gt;docker compose down; docker compose up&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Configure your web server &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Now that you application is deployed on the production server, you will have to configure any web server (Apache, Nginx, etc) to reverse proxy any calls to your domain to the port 3000 on &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's a topic for another post ;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Final tip! &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There a application called &lt;a href="https://containrrr.dev/watchtower/" rel="noopener noreferrer"&gt;Watchtower&lt;/a&gt; that can automatically fetch any new container you upload to Docker Hub and automatically pulls it and rebuild the docker compose stack. Take a look at it ;)&lt;/p&gt;

</description>
      <category>docker</category>
      <category>rails</category>
      <category>ruby</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Using Foreman to start services in development</title>
      <dc:creator>Fernando Shayani</dc:creator>
      <pubDate>Wed, 11 May 2022 23:36:47 +0000</pubDate>
      <link>https://dev.to/shayani/using-foreman-to-start-services-in-development-1iad</link>
      <guid>https://dev.to/shayani/using-foreman-to-start-services-in-development-1iad</guid>
      <description>&lt;p&gt;In any development environment it's usually needed to start many background services to be able to code properly.&lt;/p&gt;

&lt;p&gt;I don't like to keep all necessary services running in my machine all the time to save resources, so I start them only when needed; and starting them one-by-one it's too much work.&lt;/p&gt;

&lt;p&gt;Comes &lt;a href="https://github.com/ddollar/foreman"&gt;Foreman&lt;/a&gt; to the rescue! Foreman is a gem (for Ruby, but it already ported to many others languages) that will load a Procfile and start/stop the services configured by demand.&lt;/p&gt;

&lt;p&gt;For example, every time I start coding in a project, I need to run all those services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;li&gt;Webpacker&lt;/li&gt;
&lt;li&gt;Rails server&lt;/li&gt;
&lt;li&gt;Rails worker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Automation of this procedure is simple. Lets first create a &lt;code&gt;Procfile&lt;/code&gt; and save it on the project root directory.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;./Procfile&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgres: postgres -D /usr/local/var/postgres
redis: redis-server /usr/local/etc/redis.conf
webpacker: bundle exec bin/webpack-dev-server
rails: bundle exec rails server
worker: bundle exec rails jobs:work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it's easy. Just follow this simple rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;service_name: command to run it
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ foreman start

20:30:42 postgres.1 | started with pid 42458
20:30:42 rails.1    | started with pid 42459
20:30:42 worker.1   | started with pid 42460
20:30:42 redis.1    | started with pid 42461
20:30:42 webpack.1  | started with pid 42462
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you are ready to go!&lt;/p&gt;

&lt;p&gt;Thanks &lt;a href="https://github.com/ddollar"&gt;David Dollar&lt;/a&gt; for this awesome gem.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
