<?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: Rafael Almeida</title>
    <description>The latest articles on DEV Community by Rafael Almeida (@rafaelcpalmeida).</description>
    <link>https://dev.to/rafaelcpalmeida</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%2F37754%2F42d13bd1-5440-4a73-8db5-f92842a2c5e6.jpg</url>
      <title>DEV Community: Rafael Almeida</title>
      <link>https://dev.to/rafaelcpalmeida</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rafaelcpalmeida"/>
    <language>en</language>
    <item>
      <title>Managing multiple Git configurations</title>
      <dc:creator>Rafael Almeida</dc:creator>
      <pubDate>Wed, 25 Nov 2020 15:20:31 +0000</pubDate>
      <link>https://dev.to/rafaelcpalmeida/managing-multiple-git-configurations-1gdh</link>
      <guid>https://dev.to/rafaelcpalmeida/managing-multiple-git-configurations-1gdh</guid>
      <description>&lt;p&gt;Using the same computer for both work-related and personal projects may cause you to write Git commit messages with your private email on your work projects or vice-versa. That is assuming that you configured Git with the --global flag, which applies the configs to every repo on your OS user account.&lt;/p&gt;

&lt;p&gt;But, what if there was an easy way to separate your Git configs, whether you're dealing with private or work repositories, accordingly? I have great news for you: if you're using Git with, at least, version &lt;code&gt;2.13&lt;/code&gt;, you can have &lt;a href="https://git-scm.com/docs/git-config/#_conditional_includes"&gt;Conditional Includes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You might be wondering:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;That's great. But how does it help me?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Worry no more!&lt;/p&gt;

&lt;p&gt;The "middle" Git config level is the global one, which means that your configurations are stored on a &lt;code&gt;~/.gitconfig&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;Wondering how that file looks? Here's mine:&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="nb"&gt;cat&lt;/span&gt; .gitconfig
&lt;span class="o"&gt;[&lt;/span&gt;user]
 signingkey &lt;span class="o"&gt;=&lt;/span&gt; C9KF0E358V41E9C5
 name &lt;span class="o"&gt;=&lt;/span&gt; Rafael Almeida
 email &lt;span class="o"&gt;=&lt;/span&gt; rafaelcpalmeida@----.com
&lt;span class="o"&gt;[&lt;/span&gt;gpg]
 program &lt;span class="o"&gt;=&lt;/span&gt; gpg
&lt;span class="o"&gt;[&lt;/span&gt;commit]
 gpgsign &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's assume that I wanted to use:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The email &lt;a href="mailto:rafaelcpalmeida@----.com"&gt;rafaelcpalmeida@----.com&lt;/a&gt; with the GPG key C9KF0E358V41E9C5 on my private repositories.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The email &lt;a href="mailto:rafael.almeida@company.com"&gt;rafael.almeida@company.com&lt;/a&gt; with the GPG key 9VKF4E35KV4LE935 on my work repositories.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That could be easily achieved by creating two new files: one with the configurations for your personal repositories and one for the work-related ones. Here are mines:&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="nb"&gt;cat&lt;/span&gt; .gitconfig_personal
&lt;span class="o"&gt;[&lt;/span&gt;user]
 signingkey &lt;span class="o"&gt;=&lt;/span&gt; C9KF0E358V41E9C5
 name &lt;span class="o"&gt;=&lt;/span&gt; Rafael Almeida
 email &lt;span class="o"&gt;=&lt;/span&gt; rafaelcpalmeida@----.com
~
▶ &lt;span class="nb"&gt;cat&lt;/span&gt; .gitconfig_company
&lt;span class="o"&gt;[&lt;/span&gt;user]
 signingkey &lt;span class="o"&gt;=&lt;/span&gt; 9VKF4E35KV4LE935
 name &lt;span class="o"&gt;=&lt;/span&gt; Rafael Almeida
 email &lt;span class="o"&gt;=&lt;/span&gt; rafael.almeida@company.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, all I have to do is to reference them on my original &lt;code&gt;.gitconfig&lt;/code&gt; file. Again, here's mine, now updated:&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="nb"&gt;cat&lt;/span&gt; .gitconfig
&lt;span class="o"&gt;[&lt;/span&gt;gpg]
 program &lt;span class="o"&gt;=&lt;/span&gt; gpg
&lt;span class="o"&gt;[&lt;/span&gt;commit]
 gpgsign &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;includeIf &lt;span class="s2"&gt;"gitdir:~/company/"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 path &lt;span class="o"&gt;=&lt;/span&gt; .gitconfig_company
&lt;span class="o"&gt;[&lt;/span&gt;includeIf &lt;span class="s2"&gt;"gitdir:~/projects/"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 path &lt;span class="o"&gt;=&lt;/span&gt; .gitconfig_personal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file above uses the configuration of each of the files but only if the path where the repository I'm interacting with matches the path specified on the configuration file.&lt;/p&gt;

&lt;p&gt;Here's a demo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/company
▶ &lt;span class="nb"&gt;mkdir test&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd test&lt;/span&gt;
~/company/test
▶ git init
Initialized empty Git repository &lt;span class="k"&gt;in&lt;/span&gt; /Users/rafaelalmeida/company/test/.git/
~/company/test master
▶ &lt;span class="nb"&gt;touch &lt;/span&gt;a
~/company/test master
▶ git add &lt;span class="nb"&gt;.&lt;/span&gt;
~/company/test master
▶ git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Testing git configs"&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;master &lt;span class="o"&gt;(&lt;/span&gt;root-commit&lt;span class="o"&gt;)&lt;/span&gt; 6d5b06e] Testing git configs
 1 file changed, 0 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;, 0 deletions&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;
 create mode 100644 a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at my &lt;code&gt;git log&lt;/code&gt;, the output I get is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;commit 6d5b06ef2678b921436b1c17a1d5684302c9a722 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt;
Author: Rafael Almeida &amp;lt;rafael.almeida@company.com&amp;gt;
Date: Tue Nov 24 00:30:21 2020 +0000
Testing git configs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wondering what happens if I do the same on &lt;code&gt;~/projects&lt;/code&gt;? Here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/projects
▶ &lt;span class="nb"&gt;mkdir test&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd test&lt;/span&gt;
~/projects/test
▶ git init
Initialized empty Git repository &lt;span class="k"&gt;in&lt;/span&gt; /Users/rafaelalmeida/projects/test/.git/
~/projects/test master
▶ &lt;span class="nb"&gt;touch &lt;/span&gt;a
~/projects/test master
▶ git add &lt;span class="nb"&gt;.&lt;/span&gt;
~/projects/test master
▶ git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Testing git configs"&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;master &lt;span class="o"&gt;(&lt;/span&gt;root-commit&lt;span class="o"&gt;)&lt;/span&gt; 2ee78dc] Testing git configs
 1 file changed, 0 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;, 0 deletions&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;
 create mode 100644 a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's my &lt;code&gt;git log&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;commit 2ee78dcd2d154ff227982ad2e04644dd98f64c6c &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt;
Author: Rafael Almeida &amp;lt;rafaelcpalmeida@----.com&amp;gt;
Date: Tue Nov 24 00:33:30 2020 +0000
Testing git configs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;And this is how you can manage different Git configurations without any fuzz. Want to share your feedback? Let me hear you in the comments below!&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
    </item>
    <item>
      <title>Seamless CI/CD with Jenkins + Helm and Kubernetes</title>
      <dc:creator>Rafael Almeida</dc:creator>
      <pubDate>Wed, 02 Oct 2019 15:20:41 +0000</pubDate>
      <link>https://dev.to/sword-health/seamless-ci-cd-with-jenkins-helm-and-kubernetes-5e00</link>
      <guid>https://dev.to/sword-health/seamless-ci-cd-with-jenkins-helm-and-kubernetes-5e00</guid>
      <description>&lt;p&gt;There are many ways and platforms you can use to solve &lt;a href="https://en.wikipedia.org/wiki/Continuous_integration"&gt;CI&lt;/a&gt;/&lt;a href="https://en.wikipedia.org/wiki/Continuous_delivery"&gt;CD&lt;/a&gt; for your company nowadays. As we were already using Jenkins jobs for deployments and everyone at the team knew it well it was the obvious choice, but we shifted towards pipelines.&lt;/p&gt;

&lt;p&gt;To implement this you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://kubernetes.io/"&gt;Kubernetes&lt;/a&gt; cluster where you are going to deploy your applications&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://helm.sh/"&gt;Helm&lt;/a&gt; deployment files for your application&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://jenkins.io/doc/book/pipeline/"&gt;Jenkins&lt;/a&gt; CI pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The big picture
&lt;/h1&gt;

&lt;p&gt;Jenkins will fetch branches and tags from the selected repository and run all steps defined for the pipeline inside your project's &lt;code&gt;Jenskinsfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Kubernetes is an orchestration tool for containers so we need to be deploying applications as Docker containers so they can run and be managed inside this orchestration tool.&lt;/p&gt;

&lt;p&gt;Helm is a “package manager” for Kubernetes. It reads, parses and injects values into a series of “Helm templates” that in the results in a series of Kubernetes objects. Helm then bundles all of these objects into a Helm release and installs it in the configured Kubernetes cluster. You can supply to helm some input values to configure each installation which is flexible enough to install for example the same application configured differently for multiple environments (e.g dev, staging, and production).&lt;/p&gt;

&lt;h1&gt;
  
  
  The jenkins pipeline
&lt;/h1&gt;

&lt;p&gt;Here is an example of our declarative Jenkins pipeline file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;kubernetes&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="s1"&gt;'my-app'&lt;/span&gt;
            &lt;span class="n"&gt;yamlFile&lt;/span&gt; &lt;span class="s1"&gt;'JenkinsKubernetesPod.yaml'&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Run unit tests'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
              &lt;span class="c1"&gt;// The needed steps for your testing&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Build application'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
              &lt;span class="c1"&gt;// Build the app&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Docker publish'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
              &lt;span class="c1"&gt;// Publish a docker image for your application &lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Deployment'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                  &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'helm'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                      &lt;span class="c1"&gt;// Init authentication and config for your kubernetes cluster&lt;/span&gt;
                      &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"helm init --client-only --skip-refresh"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                      &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"helm upgrade --install --wait prod-my-app ./helm --namespace prod"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should include a file with the name “Jenkinsfile” in your project repository and Jenkins will use it to define the pipeline. For brevity, I only included the deployment step. In this step, you will call the Helm installation or upgrade. This will apply a &lt;code&gt;helm upgrade&lt;/code&gt; to your previously installed Helm release or if no release exists Helm will execute a &lt;code&gt;helm install&lt;/code&gt; with the given release name (e.g. prod-my-app).&lt;/p&gt;

&lt;p&gt;It’s a good idea to include the namespace as prefix or suffix for the helm release name because release names are only a name for helm and not installed as part of a Kubernetes namespace.&lt;/p&gt;

&lt;p&gt;If you attempt to install a &lt;code&gt;release-dummy&lt;/code&gt; on namespace &lt;code&gt;dev&lt;/code&gt; and a &lt;code&gt;release-dummy&lt;/code&gt; on namespace &lt;code&gt;staging&lt;/code&gt; it will fail because &lt;code&gt;release-dummy&lt;/code&gt; will already exist and Helm doesn’t care about namespace. To solve this we include a prefix of the namespace on the release name.&lt;/p&gt;

&lt;h1&gt;
  
  
  The deployment file
&lt;/h1&gt;

&lt;p&gt;Make sure you have configured your app to run as a &lt;strong&gt;Kubernetes Deployment&lt;/strong&gt; or &lt;strong&gt;StatefulSet&lt;/strong&gt; or avoid having downtime between deploys. Check the &lt;code&gt;deployment.yaml&lt;/code&gt; helm template below:&lt;br&gt;
&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;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app-dp&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;minReadySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RollingUpdate&lt;/span&gt;
    &lt;span class="na"&gt;rollingUpdate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;maxUnavailable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="na"&gt;maxSurge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&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="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.Values.app.name&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&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="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.Values.app.name&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.Values.app.name&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="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.Values.app.image.repository&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;/{{ .Values.app.image.name }}:{{ .Values.app.image.tag }}&lt;/span&gt;
        &lt;span class="na"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Always&lt;/span&gt;
        &lt;span class="na"&gt;envFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;configMapRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;config-{{ .Values.app.name }}&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="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http-{{ .Values.app.name }}&lt;/span&gt;
          &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
          &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that’s it, there are a lot of concepts to learn to put this all together but when you have it all covered up you will never have to put that much effort into deploying new applications and managing releases.&lt;/p&gt;

&lt;p&gt;When you are done you push the commits into master or create a new tag and the code will appear in your servers without no more clicking.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to use mongoDB with your Lumen API</title>
      <dc:creator>Rafael Almeida</dc:creator>
      <pubDate>Mon, 12 Aug 2019 16:48:30 +0000</pubDate>
      <link>https://dev.to/rafaelcpalmeida/how-to-use-mongodb-with-your-lumen-api-4kgm</link>
      <guid>https://dev.to/rafaelcpalmeida/how-to-use-mongodb-with-your-lumen-api-4kgm</guid>
      <description>&lt;p&gt;I’m currently building a RESTful API using &lt;a href="https://lumen.laravel.com/"&gt;Lumen&lt;/a&gt;, from the guys that brought to us &lt;a href="https://laravel.com/"&gt;Laravel&lt;/a&gt;. Lumen is a great micro-framework with most of the spectacular features from Laravel like Eloquent, caching, validation, routing, middleware and so on and so forth. The API I’m building it’s supposed to serve an, yet to develop, iOS app that it’s meant to support the information system of the college where I attend, which don’t correctly support mobile devices.&lt;/p&gt;

&lt;p&gt;This would be a pretty straightforward project but &lt;strong&gt;unfortunately,&lt;/strong&gt; they won’t make my life easy and won’t let me access the existing database. It sucks, right? However, they have a &lt;a href="https://en.wikipedia.org/wiki/SOAP"&gt;SOAP Web Service&lt;/a&gt; available that I can use. But… If I used their web service alongside my API every time I made a request it would take ages to get the information I’ve requested. This is, obviously, a shitty way to do things. So I’ve decided to implement a database where I can store the data by myself.&lt;/p&gt;

&lt;p&gt;I’m fully aware that we shouldn’t repeat data but I can’t find a better way this time. I’ve decided to develop some Python bots that would periodically fetch information using the SOAP web service and store it in the database to be later served using the REST API. I’ve decided to use &lt;a href="https://www.mongodb.com/"&gt;mongoDB&lt;/a&gt; mostly for its flexibility, performance, and scalability. I’m using mongo 3.4 so all the commands below are tested for this version.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So… How to setup Lumen to use mongoDB&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://jenssegers.com/"&gt;Jens Segers&lt;/a&gt; has a wonderful Composer package to use mongoDB with Laravel: &lt;a href="https://github.com/jenssegers/laravel-mongodb"&gt;Laravel MongoDB&lt;/a&gt;. Looking at the repo instructions you can see that, for using with Lumen and after you installed the package, edit the file &lt;code&gt;bootstrap/app.php&lt;/code&gt; and make it look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Jenssegers\Mongodb\MongodbServiceProvider&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;withEloquent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, you should create the &lt;code&gt;config/database.php&lt;/code&gt; file and it’s contents are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'default'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'mongodb'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'connections'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'mongodb'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'mongodb'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'host'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DB_HOST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s1"&gt;'port'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DB_PORT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;27017&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s1"&gt;'database'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DB_DATABASE'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s1"&gt;'username'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DB_USERNAME'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DB_PASSWORD'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s1"&gt;'options'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="s1"&gt;'database'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt; &lt;span class="c1"&gt;// sets the authentication database required by mongo 3&lt;/span&gt;
                &lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="s1"&gt;'migrations'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'migrations'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will override &lt;code&gt;vendor/laravel/lumen/config/database.php&lt;/code&gt; and it will allow you to use mongo with your Lumen project. After this you have you change our &lt;code&gt;.env&lt;/code&gt; file and append:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="no"&gt;DB_CONNECTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mongodb&lt;/span&gt;
&lt;span class="no"&gt;DB_HOST&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dbHost&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="no"&gt;DB_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;27017&lt;/span&gt;
&lt;span class="no"&gt;DB_DATABASE&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dbName&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="no"&gt;DB_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dbUser&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="no"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dbUserPassword&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Out of the box mongo doesn’t have any authentication details. You can add your own user to it using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use admin
db.createUser( { user: "&amp;lt;dbUser&amp;gt;",
          pwd: "&amp;lt;dbUserPassword&amp;gt;",
          roles: [ "userAdminAnyDatabase",
                   "dbAdminAnyDatabase",
                   "readWriteAnyDatabase"

] } )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I’m able to use Lumen’s &lt;code&gt;artisan&lt;/code&gt; commands, for instance, I can create my &lt;code&gt;users&lt;/code&gt; table using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:migration create_users_table &lt;span class="nt"&gt;--create&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;users&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’ve modified the migration file like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Blueprint&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;increments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_id'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can use &lt;code&gt;php artisan migrate&lt;/code&gt; and I’ll see my newly created collection.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>laravel</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Using Ruby on Rails 5.2 Active Storage</title>
      <dc:creator>Rafael Almeida</dc:creator>
      <pubDate>Tue, 06 Aug 2019 14:54:02 +0000</pubDate>
      <link>https://dev.to/rafaelcpalmeida/using-ruby-on-rails-5-2-active-storage-h97</link>
      <guid>https://dev.to/rafaelcpalmeida/using-ruby-on-rails-5-2-active-storage-h97</guid>
      <description>&lt;p&gt;&lt;strong&gt;Active Storage&lt;/strong&gt;, now bundled with &lt;strong&gt;Ruby on Rails 5.2&lt;/strong&gt;, allows you to easily handle your file upload, either to cloud platforms, such as &lt;strong&gt;Amazon S3&lt;/strong&gt; or &lt;strong&gt;Google Cloud Storage&lt;/strong&gt;, or even upload right into your application directory, linking your uploads to your &lt;strong&gt;Active Record&lt;/strong&gt; models with ease.&lt;/p&gt;

&lt;p&gt;In order to start using &lt;strong&gt;Active Storage&lt;/strong&gt;, you should have an existing &lt;strong&gt;Ruby on Rails 5.2&lt;/strong&gt; or greater application (freshly installed or upgraded), open your terminal in your application directory and type the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails active_storage:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will generate a brand new migration for the two necessary database tables. After this, all you need to do is run the migrations with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this everything is ready to start using &lt;strong&gt;Active Storage&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up
&lt;/h2&gt;

&lt;p&gt;To start you should declare in your &lt;code&gt;config/storage.yml&lt;/code&gt; file your &lt;strong&gt;Active Storage&lt;/strong&gt; services, one for each service that you use in your application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please, note that for the sake of this article, I’ll just be showing configurations for uploading the files to the same directory as your application, in your local disk. If you prefer to use it to upload to any cloud provider please refer to the &lt;a href="https://guides.rubyonrails.org/v5.2/active_storage_overview.html"&gt;docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;local&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Disk&lt;/span&gt;
    &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= Rails.root.join("storage") %&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you declared every service that you’ll be using it’s time to tell your application what service should be used on each environment. In this article, I’m going to configure my &lt;strong&gt;development&lt;/strong&gt; environment to use my &lt;strong&gt;local&lt;/strong&gt; storage service. In order to achieve this add the following line to &lt;code&gt;config/environments/development.rb&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Store files locally.&lt;/span&gt;
&lt;span class="s"&gt;config.active_storage.service = :local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use it
&lt;/h2&gt;

&lt;p&gt;Now that we managed to configure &lt;strong&gt;Active Storage&lt;/strong&gt; it’s time to start using it! One of the advantages of it is to easily create a relationship between the uploaded asset and your &lt;strong&gt;Active Record&lt;/strong&gt; models, as stated at the beginning of this article, so we’re to take advantage of it. I have a &lt;strong&gt;Speakers&lt;/strong&gt; model in which I intend to add an avatar to each of the &lt;strong&gt;speakers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We’ll start by informing my &lt;strong&gt;Speakers&lt;/strong&gt; model that it will have a &lt;code&gt;one-to-one&lt;/code&gt; relationship with the corresponding uploaded avatar. My model will look like:&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;Speaker&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
    &lt;span class="n"&gt;has_one_attached&lt;/span&gt; &lt;span class="ss"&gt;:avatar&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then my &lt;strong&gt;Speakers&lt;/strong&gt; controller will accept an avatar to be uploaded. My &lt;code&gt;speaker_params&lt;/code&gt; will now look like:&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;def&lt;/span&gt; &lt;span class="nf"&gt;speaker_params&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:company&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:avatar&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;The file should now look like this:&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;SpeakersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;APIController&lt;/span&gt;
    &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:set_speaker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="sx"&gt;%i[show update destroy]&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
        &lt;span class="vi"&gt;@speakers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Speaker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;
        &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="vi"&gt;@speakers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :ok&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
        &lt;span class="vi"&gt;@speaker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Speaker&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="n"&gt;speaker_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="vi"&gt;@speaker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :created&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
        &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="vi"&gt;@speaker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;status: :ok&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;
        &lt;span class="vi"&gt;@speaker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;speaker_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="ss"&gt;:no_content&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;
        &lt;span class="vi"&gt;@speaker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;
        &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="ss"&gt;:no_content&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;    &lt;span class="kp"&gt;private&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;speaker_params&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:company&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="ss"&gt;:avatar&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:social_media&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_speaker&lt;/span&gt;
        &lt;span class="vi"&gt;@speaker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Speaker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have to specify on my &lt;strong&gt;request&lt;/strong&gt; body a field named &lt;strong&gt;avatar&lt;/strong&gt; and its value will be a file, that’s going to be used as the speaker avatar.&lt;/p&gt;

&lt;p&gt;After you finish your &lt;strong&gt;POST&lt;/strong&gt; request and you navigate to the &lt;code&gt;storage&lt;/code&gt; directory you’ll see a newly created directory containing your uploaded file. If you wish to verify that the file is linked to your speaker you can start &lt;code&gt;rails console&lt;/code&gt; and type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;irb&lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt;:001:0&amp;gt; speaker &lt;span class="o"&gt;=&lt;/span&gt; Speaker.find&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;#&amp;lt;Speaker id: 1, name: “Rafael”, email: “rafael.almeida@xing.com”, company: “XING”, social_media: nil, created_at: “2018–10–02 09:58:54”, updated_at: “2018–10–02 09:58:54”&amp;gt;&lt;/span&gt;
irb&lt;span class="o"&gt;(&lt;/span&gt;main&lt;span class="o"&gt;)&lt;/span&gt;:002:0&amp;gt; app.url_for&lt;span class="o"&gt;(&lt;/span&gt;speaker.avatar&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; “http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--372a32ffdde03c2f2a37f407e63d10c909fd52ba/xing-photo.jpg&lt;span class="s2"&gt;"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Et voilá&lt;/em&gt;, &lt;strong&gt;Active Storage&lt;/strong&gt; is configured and ready to be used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus tip
&lt;/h2&gt;

&lt;p&gt;If you execute a &lt;strong&gt;GET&lt;/strong&gt; request on your &lt;strong&gt;API&lt;/strong&gt; you’ll get the information about your &lt;strong&gt;speaker&lt;/strong&gt; that you defined on your migration, like the example below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rafael"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rafael.almeida@xing.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"company"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"XING"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"social_media"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2018-10-02T09:59:28.494Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2018-10-02T09:59:28.497Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, you also might want to get the associated avatar. We can use a &lt;strong&gt;serializer&lt;/strong&gt; in order to achieve what we intend. You’ll need to add &lt;code&gt;gem 'active_model_serializers'&lt;/code&gt; and then include the following line in every &lt;strong&gt;controller&lt;/strong&gt; that you want to get override with the &lt;strong&gt;serializer&lt;/strong&gt;: &lt;code&gt;include ActionController::Serialization&lt;/code&gt;. After that you can use &lt;code&gt;rails g serializer speaker&lt;/code&gt; and &lt;strong&gt;Rails&lt;/strong&gt; will generate the file for you.&lt;/p&gt;

&lt;p&gt;In order to get the associated &lt;strong&gt;avatar&lt;/strong&gt; your &lt;code&gt;serializer&lt;/code&gt; should look like:&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;SpeakerSerializer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveModel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Serializer&lt;/span&gt;
  &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:company&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:avatar&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;avatar&lt;/span&gt;
    &lt;span class="n"&gt;rails_blob_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only_path: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attached?&lt;/span&gt;
  &lt;span class="k"&gt;end&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 if you re-run your &lt;strong&gt;GET&lt;/strong&gt; request you’ll see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"speaker"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rafael"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rafael.almeida@xing.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"company"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"XING"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"avatar"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19–515a0de8817b3529b5d3d168871cebf6ccee0463/xing-photo.jpg"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’re now able to see the avatar associated with every speaker.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>HTTP Methods and why you should be using them on your API</title>
      <dc:creator>Rafael Almeida</dc:creator>
      <pubDate>Fri, 02 Aug 2019 11:10:54 +0000</pubDate>
      <link>https://dev.to/rafaelcpalmeida/http-methods-and-why-you-should-be-using-them-on-your-api-4bfh</link>
      <guid>https://dev.to/rafaelcpalmeida/http-methods-and-why-you-should-be-using-them-on-your-api-4bfh</guid>
      <description>&lt;p&gt;Every single one of us has, even if without knowing, used the &lt;strong&gt;HTTP&lt;/strong&gt; protocol before. Otherwise, I wouldn’t have written this on DEV Community and, therefore, you wouldn’t be reading it.&lt;/p&gt;

&lt;p&gt;When writing &lt;strong&gt;REST API&lt;/strong&gt;’s one should ensure that it uses the standard &lt;strong&gt;HTTP&lt;/strong&gt; methods. These are a great pillar to build a stable and, very important, scalable &lt;strong&gt;API&lt;/strong&gt;. &lt;strong&gt;GET&lt;/strong&gt;, &lt;strong&gt;POST&lt;/strong&gt;, &lt;strong&gt;PUT&lt;/strong&gt;… which one should I use? My answer to that is: depends on what you want to do!&lt;/p&gt;

&lt;h3&gt;
  
  
  When should I use each method?
&lt;/h3&gt;

&lt;p&gt;The main &lt;strong&gt;HTTP&lt;/strong&gt; verbs, or methods if you prefer to call them that, are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GET&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;POST&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PUT&lt;/strong&gt; / &lt;strong&gt;PATCH&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DELETE&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may be like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Hey thanks, I didn’t know about that! But… when am I supposed to use each one of them?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let me explain them to you (and hopefully don’t make this too boring)!&lt;/p&gt;

&lt;h5&gt;
  
  
  GET
&lt;/h5&gt;

&lt;p&gt;If you check the specification of the HTTP/1.1 protocol it says, and I quote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in the response and not the source text of the process, unless that text happens to be the output of the process.”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simplifying this is to say that the &lt;strong&gt;GET&lt;/strong&gt; verb (or method) should be used to retrieve the information you’re looking for. Take the following &lt;strong&gt;URL&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://api-url.dev/api/v1/users/1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It should retrieve all the accessible information about the user with the &lt;strong&gt;ID&lt;/strong&gt; 1.&lt;/p&gt;

&lt;h5&gt;
  
  
  POST
&lt;/h5&gt;

&lt;p&gt;Let us check the specification of the HTTP/1.1 protocol yet again. It says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. POST is designed to allow a uniform method to cover the following functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Annotation of existing resources;&lt;/li&gt;
&lt;li&gt;Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;&lt;/li&gt;
&lt;li&gt;Providing a block of data, such as the result of submitting a form, to a data-handling process;&lt;/li&gt;
&lt;li&gt;Extending a database through an append operation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, these are a lot of words to say that the &lt;strong&gt;POST&lt;/strong&gt; verb to store information on the server.&lt;/p&gt;

&lt;p&gt;Take the following URL:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://api-url.dev/api/v1/users&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This should be used to create a new user. You can send all the required information (username, password, etc.) using the body of the &lt;strong&gt;HTTP&lt;/strong&gt; request you’re going to make.&lt;/p&gt;

&lt;h5&gt;
  
  
  PUT / PATCH
&lt;/h5&gt;

&lt;p&gt;Let us check the HTTP/1.1 protocol one more time. What does it say about &lt;strong&gt;PUT&lt;/strong&gt; verb?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, the text above is telling us that we should use the &lt;strong&gt;PUT&lt;/strong&gt; verb to update an existing resource, say, for instance, an existing user.&lt;/p&gt;

&lt;p&gt;Using the URL:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://api-url.dev/api/v1/users/1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The system should update the information regarding the user with the ID 1 with the information sent in the request.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But… what about the &lt;strong&gt;PATCH&lt;/strong&gt; verb?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Right! The &lt;strong&gt;PATCH&lt;/strong&gt; verb. Say, for instance, that you want to update the user with the &lt;strong&gt;ID&lt;/strong&gt; 1, like the example right above, but you just want to send just the newly updated field, let’s say the password field. In this case, you should use the &lt;strong&gt;PATCH&lt;/strong&gt; verb. Why? Because you’re just sending a fragment of the user entity, which in this example is the password, thus this verb is adequate as you’re &lt;strong&gt;PATCH&lt;/strong&gt;ing the given user.&lt;/p&gt;

&lt;h5&gt;
  
  
  DELETE
&lt;/h5&gt;

&lt;p&gt;Ah, the last but not the least: the &lt;strong&gt;DELETE&lt;/strong&gt; verb. So, checking the specification one last time (finally no?) we get the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The DELETE method requests that the origin server delete the resource identified by the Request-URI. This method MAY be overridden by human intervention (or other means) on the origin server. The client cannot be guaranteed that the operation has been carried out, even if the status code returned from the origin server indicates that the action has been completed successfully. However, the server SHOULD NOT indicate success unless, at the time the response is given, it intends to delete the resource or move it to an inaccessible location.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Deciphering the slightly confusing text it says that you should be using the &lt;strong&gt;DELETE&lt;/strong&gt; verb every time that you want to remove some resource from the server.&lt;/p&gt;

&lt;p&gt;If you execute a &lt;strong&gt;DELETE&lt;/strong&gt; request on the following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://api-url.dev/api/v1/users/1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The server should delete the user with the &lt;strong&gt;ID&lt;/strong&gt; 1 and, perhaps, all the resources associated with him.&lt;/p&gt;

&lt;p&gt;And that’s it! I’ve covered up everything I’ve proposed at the beginning of the article. Hope that you enjoyed the reading and let me know if you have any question or suggestion to improve.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Automate Your Slack Interactions</title>
      <dc:creator>Rafael Almeida</dc:creator>
      <pubDate>Mon, 29 Jul 2019 11:26:13 +0000</pubDate>
      <link>https://dev.to/rafaelcpalmeida/automate-your-slack-interactions-37ed</link>
      <guid>https://dev.to/rafaelcpalmeida/automate-your-slack-interactions-37ed</guid>
      <description>&lt;p&gt;I’m a big fan of automating repetitive tasks and I always try to automate everything I can. Remember the &lt;a href="https://www.businessinsider.com/programmer-automates-his-job-2015-11"&gt;guy that automated part of his job&lt;/a&gt;? I try to do some similar stuff too! Imagine the following scenario: every time that you close your MacBook Pro lid it sends a message, telling your team that you’re gone for the day. In this article, I’m going to show how to do this!&lt;/p&gt;

&lt;p&gt;To send messages on &lt;strong&gt;Slack&lt;/strong&gt;, you’ll need a &lt;strong&gt;Slack Access Token&lt;/strong&gt;. To get one you need to create a new &lt;strong&gt;Slack app&lt;/strong&gt;, install in your workspace, go to OAuth &amp;amp; Permissions and copy your generated &lt;strong&gt;OAuth Access Token&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To be able to execute scripts when your Mac goes to sleep or wakes up we’ll use &lt;a href="https://www.bernhard-baehr.de/"&gt;Bernhard Baehr&lt;/a&gt;’s &lt;a href="https://www.bernhard-baehr.de/sleepwatcher_2.2.tgz"&gt;SleepWatcher 2.2&lt;/a&gt;. After you download the file, unpack it and open a new Terminal window on its directory and type the following:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /usr/local/sbin /usr/local/share/man/man8

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp &lt;/span&gt;sleepwatcher /usr/local/sbin

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp &lt;/span&gt;sleepwatcher.8 /usr/local/share/man/man8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this article, I’m just going to write about the &lt;strong&gt;sleep&lt;/strong&gt; event trigger. If you want to know about more events or read the documentation just type:&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="nv"&gt;$ &lt;/span&gt;man sleepwatcher
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that &lt;strong&gt;SleepWatcher&lt;/strong&gt; is in the correct place you can try the script that’s going to be executed with the following command:&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="nv"&gt;$ &lt;/span&gt;/usr/local/sbin/sleepwatcher &lt;span class="nt"&gt;--verbose&lt;/span&gt; &lt;span class="nt"&gt;--sleep&lt;/span&gt; /path/to/your/sleepscript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you’re finished with the tests and everything behaves as expected is time to setup &lt;strong&gt;SleepWatcher&lt;/strong&gt; to run as a daemon. To do this you can type the following commands:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp &lt;/span&gt;config/de.bernhard-baehr.sleepwatcher-20compatibility.plist /Library/LaunchDaemons/de.bernhard-baehr.sleepwatcher.plist
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp &lt;/span&gt;config/rc.&lt;span class="k"&gt;*&lt;/span&gt; /usr/local/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that just execute to start your daemon.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;launchctl load /Library/LaunchDaemons/de.bernhard-baehr.sleepwatcher.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that everything is ready you need to write the script that’s going to be executed every time your computer goes to sleep. We’re calling it .sleep and make it executable:&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; ~/.sleep
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ~/.sleep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this file, we’re going to place the code that’s going to be used to post our messages to &lt;strong&gt;Slack&lt;/strong&gt;. Mine looks like:&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="nv"&gt;STARTING_TIME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"17:00"&lt;/span&gt;

&lt;span class="nv"&gt;ENDING_TIME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"19:00"&lt;/span&gt;

&lt;span class="nv"&gt;CURRENT_TIME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%H:%M&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;CURRENT_DATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="s2"&gt;"+%d/%m/%Y"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;READ_DATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.say_message.lock&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CURRENT_TIME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STARTING_TIME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CURRENT_TIME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ENDING_TIME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$READ_DATE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CURRENT_DATE&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="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xoxp-2…

    &lt;span class="nv"&gt;CHANNEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="c"&gt;#channel_name&lt;/span&gt;

    &lt;span class="nb"&gt;declare&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;EXPRESSIONS&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"Write"&lt;/span&gt; &lt;span class="s2"&gt;"Your"&lt;/span&gt; &lt;span class="s2"&gt;"Expressions"&lt;/span&gt; &lt;span class="s2"&gt;"Here"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="nv"&gt;SELECTED_EXPRESSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EXPRESSIONS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$RANDOM&lt;/span&gt;&lt;span class="p"&gt; % &lt;/span&gt;&lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;EXPRESSIONS&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt; ]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

    curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;

        &lt;span class="nt"&gt;--connect-timeout&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;

        &lt;span class="nt"&gt;--max-time&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;

        &lt;span class="nt"&gt;--retry&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;

        &lt;span class="nt"&gt;--retry-delay&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;

        &lt;span class="nt"&gt;--retry-max-time&lt;/span&gt; 60 &lt;span class="se"&gt;\&lt;/span&gt;

        &lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="s1"&gt;'content-type: multipart/form-data'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

        &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

        &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s2"&gt;"channel=&lt;/span&gt;&lt;span class="nv"&gt;$CHANNEL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

        &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SELECTED_EXPRESSION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

        &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;as_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

        https://slack.com/api/chat.postMessage

        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$CURRENT_DATE&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.say_message.lock

&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me explain the script line by line.&lt;/p&gt;

&lt;h2&gt;
  
  
  Script explanation
&lt;/h2&gt;

&lt;p&gt;I’m using the following variables to specify that the message is meant to be sent only between 17:00 and 19:00&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="nv"&gt;STARTING_TIME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"17:00"&lt;/span&gt;

&lt;span class="nv"&gt;ENDING_TIME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"19:00"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are used to ensure that the message is only sent once per day, to prevent sending it every time that you lock your computer, for instance.&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="nv"&gt;CURRENT_TIME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%H:%M&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;CURRENT_DATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="s2"&gt;"+%d/%m/%Y"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;READ_DATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.say_message.lock&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The if condition bellow allows me to ensure that the conditions I’ve specified above are met. Which are: the message is only sent between 17:00 and 19:00 and only executes once per day.&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="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CURRENT_TIME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STARTING_TIME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CURRENT_TIME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ENDING_TIME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$READ_DATE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CURRENT_DATE&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

fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To send the message to the desired channel you have to specify the token you got from &lt;strong&gt;Slack&lt;/strong&gt; and the channel to post the message. I also have an array of expressions to be randomized later. This is meant to send a different message. To achieve this I have the following lines:&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="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xoxp-2[…]

&lt;span class="nv"&gt;CHANNEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="c"&gt;#channel_name&lt;/span&gt;

&lt;span class="nb"&gt;declare&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;EXPRESSIONS&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"Write"&lt;/span&gt; &lt;span class="s2"&gt;"Your"&lt;/span&gt; &lt;span class="s2"&gt;"Expressions"&lt;/span&gt; &lt;span class="s2"&gt;"Here"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;SELECTED_EXPRESSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EXPRESSIONS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$RANDOM&lt;/span&gt;&lt;span class="p"&gt; % &lt;/span&gt;&lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;EXPRESSIONS&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="p"&gt; ]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When everything is set we need to send our message to &lt;strong&gt;Slack API&lt;/strong&gt;. This is done using &lt;strong&gt;cURL&lt;/strong&gt;. These are my configs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="nt"&gt;--connect-timeout&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="nt"&gt;--max-time&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="nt"&gt;--retry&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="nt"&gt;--retry-delay&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="nt"&gt;--retry-max-time&lt;/span&gt; 60 &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="s1"&gt;'content-type: multipart/form-data'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s2"&gt;"channel=&lt;/span&gt;&lt;span class="nv"&gt;$CHANNEL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SELECTED_EXPRESSION&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;as_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

https://slack.com/api/chat.postMessage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’m telling &lt;strong&gt;cURL&lt;/strong&gt; to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each attempt last 10 seconds with --max-time 10&lt;/li&gt;
&lt;li&gt;Retry 10 times using --retry 10&lt;/li&gt;
&lt;li&gt;Disable cURL sleep between retries using --retry-delay 0&lt;/li&gt;
&lt;li&gt;Wait 60 seconds max using --retry-max-time 60&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code above will send a POST request to &lt;code&gt;https://slack.com/api/chat.postMessage&lt;/code&gt; with the specified payload. You can check more about &lt;strong&gt;postMessage&lt;/strong&gt; endpoint reading Slack &lt;a href="https://api.slack.com/methods/chat.postMessage"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After the execution of the request I’m updating the “lock” file with the new date with the line:&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="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$CURRENT_DATE&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.say_message.lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is meant to ensure that only one message per day is sent.&lt;/p&gt;

&lt;p&gt;This is how I automated my interactions with Slack. Let me know your thoughts on this using the comments below.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>bash</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Enhancing your git commit messages</title>
      <dc:creator>Rafael Almeida</dc:creator>
      <pubDate>Thu, 25 Jul 2019 09:56:41 +0000</pubDate>
      <link>https://dev.to/rafaelcpalmeida/enhancing-your-git-commit-messages-3mk7</link>
      <guid>https://dev.to/rafaelcpalmeida/enhancing-your-git-commit-messages-3mk7</guid>
      <description>&lt;p&gt;If you're reading this chances are that you're already aware of what git is and you also work with any ticket-based software, like Jira. In this article, I'm going to show you how automatically prepend the ticket ID you're working on to your commit message, assuming that you're using you're branch names similar to &lt;code&gt;feature/ABC-1234-Feature-testing&lt;/code&gt;.&lt;br&gt;
To achieve this, you're going to use &lt;strong&gt;git hooks&lt;/strong&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Git hooks
&lt;/h1&gt;

&lt;p&gt;According to &lt;a href="https://githooks.com/"&gt;Git Hooks&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Git hooks are scripts that Git executes before or after events such as: commit, push, and receive. Git hooks are a built-in feature - no need to download anything. Git hooks are run locally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that you know what you need, just create a new file under &lt;code&gt;.git/hooks&lt;/code&gt; folder. Name it prepare-commit-msg.&lt;br&gt;
Copy the code below and paste it into your newly created file.&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;# List the branches that don't apply bellow&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;$BRANCHES_TO_IGNORE&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="nv"&gt;BRANCHES_TO_IGNORE&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;master develop staging &lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Pick the current branch name and check if it is excluded&lt;/span&gt;
&lt;span class="nv"&gt;BRANCH_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git symbolic-ref &lt;span class="nt"&gt;--short&lt;/span&gt; HEAD&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;BRANCH_IGNORED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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;BRANCHES_TO_IGNORE&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &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="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Remove the unnecessary parts&lt;/span&gt;
&lt;span class="nv"&gt;TRIMMED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$BRANCH_NAME&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'s:^(\w+)\/([^-]*-[^-]*)-.*:\2:'&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# If it isn't excluded, prepend the part that interests us to the given commit message&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;-n&lt;/span&gt; &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="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;  &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$BRANCH_IGNORED&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 1 &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;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt;.bak &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"1s/^/&lt;/span&gt;&lt;span class="nv"&gt;$TRIMMED&lt;/span&gt;&lt;span class="s2"&gt; - /"&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the creation of the file, you'll need to give it its proper permissions. This can be achieved by executing &lt;code&gt;chmod +x prepare-commit-msg&lt;/code&gt;.&lt;br&gt;
If you want to see it in action just make a new commit and type any message you want. You should see now, given the branch name above, something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;commit 976f4354779a824e5edfd851857b26c9bcfd3e14 &lt;span class="o"&gt;(&lt;/span&gt;feature/ABC-1234-Feature-testing&lt;span class="o"&gt;)&lt;/span&gt;
Author: Rafael &amp;lt;email@example.com&amp;gt;
Date:   Tue Jul 23 17:35:25 2019 +0100

    ABC-1234 - This is a testing message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Apply your changes globally
&lt;/h1&gt;

&lt;p&gt;Now that I've shown you how to improve your commit messages you'll want to apply the condition to every other repo in your machine, right? I'm going to show you how to achieve it.&lt;br&gt;
The first step is to create a folder that's going to contain all of your hooks. I'm using this &lt;a href="https://github.com/rafaelcpalmeida/git-hooks-templates"&gt;repo&lt;/a&gt; I've created but you can use whichever you prefer. After having your own folder you execute the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; init.templatedir &lt;span class="s1"&gt;'~/projects/git-hooks-templates'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within you should have another folder named &lt;code&gt;hooks&lt;/code&gt;, this is where we're going to place our git hooks.&lt;br&gt;
Now that the folder structure is correct you can copy the file created above into the, in this example (yours might differ) &lt;code&gt;~/projects/git-hooks-templates&lt;/code&gt; directory. The command to execute after is:&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="nb"&gt;chmod &lt;/span&gt;a+x ~/projects/git-hooks-templates/hooks/prepare-commit-msg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have everything set up. Every time that you create or clone new repositories your commit messages will be appended with the ticket ID based on the branch that you're working on.&lt;/p&gt;

</description>
      <category>git</category>
      <category>bash</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
