<?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: Ali Ilman</title>
    <description>The latest articles on DEV Community by Ali Ilman (@thealiilman).</description>
    <link>https://dev.to/thealiilman</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%2F29494%2Ff937e46c-6d27-4920-bc80-25d5c49b48ca.jpeg</url>
      <title>DEV Community: Ali Ilman</title>
      <link>https://dev.to/thealiilman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thealiilman"/>
    <language>en</language>
    <item>
      <title>8 Tips on Giving Effective Code Reviews</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Thu, 07 Jan 2021 03:17:00 +0000</pubDate>
      <link>https://dev.to/thealiilman/8-tips-on-giving-effective-code-reviews-5dj5</link>
      <guid>https://dev.to/thealiilman/8-tips-on-giving-effective-code-reviews-5dj5</guid>
      <description>&lt;p&gt;A pull request isn't just the responsibility of the author, but also the reviewer. In this article, I'll be sharing 8 tips on giving effective code reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Practice conventional comments
&lt;/h2&gt;

&lt;p&gt;I've been practicing &lt;a href="https://conventionalcomments.org/"&gt;conventional comments&lt;/a&gt; for around 6 months. I find it to be a good practice. Here are a few reasons.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The intention of our comment is clear&lt;/li&gt;
&lt;li&gt;The separation between the &lt;em&gt;topic&lt;/em&gt; of the comment and the &lt;em&gt;example&lt;/em&gt; and / or &lt;em&gt;reasoning&lt;/em&gt; of the comment is clear&lt;/li&gt;
&lt;li&gt;The author knows what they should prioritise on because our comments are well-labelled&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  2. Suggest changes by masking them as questions
&lt;/h2&gt;

&lt;p&gt;When we mask our suggestions as questions, they can be thought-provoking to the author and the tone of our suggestion is highly likely to come across as friendly. Here are a few examples.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What if we rename this boolean variable from &lt;code&gt;invitationAccepted&lt;/code&gt; to &lt;code&gt;hasUserAcceptedInvitation&lt;/code&gt;? &lt;code&gt;hasUserAcceptedInvitation&lt;/code&gt; is more clearer than &lt;code&gt;invitationAccepted&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Since we're doing &lt;code&gt;${address.city}, ${address.country}&lt;/code&gt; more than once throughout these files, how about moving this combining of city and country into the &lt;code&gt;Address&lt;/code&gt; class?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3. Add an example in our suggestion
&lt;/h2&gt;

&lt;p&gt;Adding an example in our suggestion can be more beneficial than leaving just a reason. An example coupled with a reason might just give the author a eureka moment. 💡&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Replace 'you' with 'we'
&lt;/h2&gt;

&lt;p&gt;The effect of using 'we' instead of 'you' with people that know us well may not be significant, but with people we've not worked with before, it can provide a psychological difference, especially to those new to the industry. It can make them feel welcomed and makes the code review feel like a learning session.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Mind your nitpicks
&lt;/h2&gt;

&lt;p&gt;Some nitpicks are necessary, but some of them are not. A code review filled with unnecessary nitpicks can affect the author's self-esteem and might even make us look unkind. How do we decide when to nitpick?&lt;/p&gt;

&lt;p&gt;I suggest asking ourselves whether the code we're reviewing is misleading.&lt;/p&gt;

&lt;p&gt;Is there a typo on user-facing content or a variable with a misleading name? If there is, it is a necessary nitpick.&lt;/p&gt;

&lt;p&gt;Is our suggestion purely a &lt;em&gt;stylistic change&lt;/em&gt; that makes no positive difference in readability? If it is, then it is an unnecessary nitpick.&lt;/p&gt;

&lt;p&gt;But what if we want to enforce a convention within the codebase such as using double-quoted strings?&lt;br&gt;
Then this should be taken care of by a linter. In JavaScript, there is &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;. In Ruby, there is &lt;a href="https://rubocop.org/"&gt;RuboCop&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. If you're reviewing code, dedicate some time for it, don't rush
&lt;/h2&gt;

&lt;p&gt;Reviewing code is also a part of the job. When we do our code review in haste, it's easy for sneaky bugs to slip through. If you're in a rush, I suggest doing the code review later if it's not urgent.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Use emojis and GIFs!
&lt;/h2&gt;

&lt;p&gt;Most of the time, we communicate with the author of the pull request through text. It's easy for them to misinterpret our comments negatively, especially if we don't know each other well. Using emojis and GIFs can keep the atmosphere warm. Though please avoid leaving sarcastic emojis or GIFs because sarcasm doesn't transfer well through text. 😁&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Leave a summary when necessary
&lt;/h2&gt;

&lt;p&gt;Sometimes, we encounter some code that are similar and require similar changes. We shouldn't be leaving the same comment more than a few times as it can make the author feel overwhelmed. Instead, leave a summary. Here's an example.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The rest looks good to me! Just a few minor suggestions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Link to code block A&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Link to code block B&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Link to code block C&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Link to code block D&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These blocks of code are doing the same thing. How about creating a reusable method?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;When we review code, the objective isn't just to tidy up code and then merging the pull request for the sake of keeping a project moving. A code review is also a place for learning. Not just for the author, but also for the reviewer. Making ourselves approachable is one way of making code review a fun process.&lt;/p&gt;

&lt;p&gt;If you find this article helpful, please spread the word! If you're looking for tips on opening effective pull requests, &lt;a href="https://dev.to/thealiilman/3-tips-on-opening-effective-pull-requests-31p4"&gt;this article&lt;/a&gt; is just for you!&lt;/p&gt;

&lt;p&gt;Do follow me on &lt;a href="https://twitter.com/thealiilman"&gt;Twitter&lt;/a&gt; to read about my findings while programming or my feelings of joy and despair while watching football. I'm also active on &lt;a href="https://instagram.com/thealiilman"&gt;Instagram&lt;/a&gt; and &lt;a href="https://www.goodreads.com/user/show/93420883-ali-ilman"&gt;Goodreads&lt;/a&gt; where I frequently share what I'm reading and what I've read.&lt;/p&gt;

&lt;p&gt;Thanks for reading! ✌️&lt;/p&gt;

</description>
      <category>git</category>
      <category>tutorial</category>
      <category>productivity</category>
      <category>github</category>
    </item>
    <item>
      <title>3 Tips on Opening Effective Pull Requests</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Mon, 14 Dec 2020 09:07:34 +0000</pubDate>
      <link>https://dev.to/thealiilman/3-tips-on-opening-effective-pull-requests-31p4</link>
      <guid>https://dev.to/thealiilman/3-tips-on-opening-effective-pull-requests-31p4</guid>
      <description>&lt;p&gt;When I first started working almost 3 years ago, I couldn't see the need to include anything in the description of my pull requests. I had felt that the title is enough. In some cases, this is true. But in other cases, a &lt;em&gt;Fix broken ABC feature&lt;/em&gt; sounds vague to code reviewers. Being provided at least some context about the pull request can be helpful.&lt;/p&gt;

&lt;p&gt;In this article, I'll be sharing 3 tips on opening effective pull requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Describe why you made the changes
&lt;/h2&gt;

&lt;p&gt;Describing our changes is a great way to provide the context of the pull request (and commit). It can be helpful now and in the future. Here are reasons why. 👇&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The reviewer can view the pull request from a certain angle, providing potentially better suggestions&lt;/li&gt;
&lt;li&gt;Tracking down bugs in the future are easier as we would have an idea as to why certain changes were made&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  2. Keep the pull request small
&lt;/h2&gt;

&lt;p&gt;When a pull request is big, the reviewer can feel overloaded with information. When this happens, it can affect how the reviewer views the correlation between a piece of code with another and worse, a sneaky bug can slip through. But when exactly can a pull request be considered as big?&lt;/p&gt;

&lt;p&gt;We can use &lt;a href="http://smartbear.com/resources/case-studies/cisco-systems-collaborator/"&gt;this study&lt;/a&gt; as a guide and follow our instincts because pull requests are unique.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A SmartBear study of a Cisco Systems programming team revealed that developers should review no more than 200 to 400 lines of code (LOC) at a time. The brain can only effectively process so much information at a time; beyond 400 LOC, the ability to find defects diminishes.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How should we decide to keep our pull requests small? Ask ourselves this question whenever we think about fixing a bug or implementing another feature altogether.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Can this be done separately? If yes, then do in a separate pull request.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3. Write a changelog
&lt;/h2&gt;

&lt;p&gt;Unlike my first two tips, this is rather insignificant. Before I started describing my changes, I tend to just include a changelog to give the reviewer an idea of what to expect. Nowadays, the changelog acts as an addition to my description. A changelog could look like this.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bGSquw55--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xnvph3dcoafbbkc8yhy7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bGSquw55--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xnvph3dcoafbbkc8yhy7.png" alt="changelog-example" width="880" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find this article helpful, please spread the word!&lt;/p&gt;

&lt;p&gt;Do follow me on &lt;a href="https://twitter.com/thealiilman"&gt;Twitter&lt;/a&gt; to read about my findings while programming or my feelings of joy and despair while watching football. I'm also active on &lt;a href="https://instagram.com/thealiilman"&gt;Instagram&lt;/a&gt; and &lt;a href="https://www.goodreads.com/user/show/93420883-ali-ilman"&gt;Goodreads&lt;/a&gt; where I frequently share what I'm reading and what I've read.&lt;/p&gt;

&lt;p&gt;Thanks for reading! ✌️&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>codenewbie</category>
      <category>productivity</category>
    </item>
    <item>
      <title>What is a Kubernetes Object</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Mon, 17 Aug 2020 00:13:41 +0000</pubDate>
      <link>https://dev.to/thealiilman/what-is-a-kubernetes-object-3hn5</link>
      <guid>https://dev.to/thealiilman/what-is-a-kubernetes-object-3hn5</guid>
      <description>&lt;p&gt;A Kubernetes object is &lt;em&gt;something&lt;/em&gt; that exists in a Kubernetes cluster. There are configuration files we can write, and these files are used to create Kubernetes objects.&lt;/p&gt;

&lt;p&gt;In Kubernetes, there are &lt;em&gt;object types&lt;/em&gt;. An object type has its own purpose.&lt;br&gt;
An example of an object type is the &lt;strong&gt;Pod&lt;/strong&gt; object type. Pod is used to run a container.&lt;/p&gt;

&lt;p&gt;To specify an object type in a Kubernetes config file, we use the &lt;code&gt;kind&lt;/code&gt; property.&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;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/"&gt;https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>learning</category>
    </item>
    <item>
      <title>What is a Kubernetes Cluster</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Wed, 12 Aug 2020 11:12:04 +0000</pubDate>
      <link>https://dev.to/thealiilman/what-is-a-kubernetes-cluster-2c5j</link>
      <guid>https://dev.to/thealiilman/what-is-a-kubernetes-cluster-2c5j</guid>
      <description>&lt;p&gt;A Kubernetes cluster is a group of machines that are connected to each other to work as a single block.&lt;/p&gt;

&lt;p&gt;A Kubernetes cluster consists of two resources.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Control Plane&lt;/li&gt;
&lt;li&gt;The Nodes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The control plane and the nodes communicate with each other through the &lt;a href="https://kubernetes.io/docs/concepts/overview/kubernetes-api/"&gt;Kubernetes API&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Control Plane
&lt;/h2&gt;

&lt;p&gt;The control plane is responsible for managing our cluster. It can be deployments, scaling etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Nodes
&lt;/h2&gt;

&lt;p&gt;A node works as a machine within a Kubernetes cluster. A node runs an application, and it handles container operations through Docker. A node can be either a virtual machine or a physical computer.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>learning</category>
    </item>
    <item>
      <title>The String#chars method</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Sun, 26 Apr 2020 13:46:05 +0000</pubDate>
      <link>https://dev.to/thealiilman/the-string-chars-method-bdi</link>
      <guid>https://dev.to/thealiilman/the-string-chars-method-bdi</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://ali-ilman.com/blog/the-string-chars-method"&gt;https://ali-ilman.com/blog/the-string-chars-method&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I was browsing the web and I noticed Ruby code that utilises a &lt;code&gt;String&lt;/code&gt; instance method called &lt;code&gt;chars&lt;/code&gt;.&lt;br&gt;
Until today, I'd never used nor heard of &lt;code&gt;String#chars&lt;/code&gt;. What does it do?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;String#chars&lt;/code&gt; is used to return an array of characters within a string.&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="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Ali'&lt;/span&gt;
&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chars&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"l"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"i"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do note that it &lt;strong&gt;does not&lt;/strong&gt; work similarly to &lt;code&gt;String#split&lt;/code&gt;, although we can achieve the same result.&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="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Ali"&lt;/span&gt;
&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"l"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"i"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So how are &lt;code&gt;String#chars&lt;/code&gt; and &lt;code&gt;String#split&lt;/code&gt; different to each other?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;String#split&lt;/code&gt; uses a regular expression to divide characters within a string, thus returning an array.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;String#chars&lt;/code&gt; parses the byte of each character within a string and then it returns an array.&lt;/p&gt;

&lt;p&gt;Cheers for reading! 🤓&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>tutorial</category>
      <category>todayilearned</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Specifying a Template and a Layout through Action Mailer's mail function</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Mon, 13 Apr 2020 14:52:51 +0000</pubDate>
      <link>https://dev.to/thealiilman/specifying-a-template-and-a-layout-through-action-mailer-s-mail-function-5dfd</link>
      <guid>https://dev.to/thealiilman/specifying-a-template-and-a-layout-through-action-mailer-s-mail-function-5dfd</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://ali-ilman.com/blog/specifying-a-template-and-a-layout-through-action-mailer-mail-function"&gt;https://ali-ilman.com/blog/specifying-a-template-and-a-layout-through-action-mailer-mail-function&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Photo by &lt;a href="https://unsplash.com/photos/AwmCuTXL97Q"&gt;Mikaela Wiedenhoff&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this article, we'll take a look at one of the lesser-known features within Action Mailer, that is specifying a template and a layout through the &lt;code&gt;mail&lt;/code&gt; function. This can come in handy if we want to display specific content for certain emails without creating unnecessary mailers. 🧠&lt;/p&gt;
&lt;h2&gt;
  
  
  Specifying a template
&lt;/h2&gt;

&lt;p&gt;There are a few ways to specify a template through the &lt;code&gt;mail&lt;/code&gt; function. The &lt;code&gt;mail&lt;/code&gt; function accepts keyword arguments called &lt;code&gt;template_path&lt;/code&gt; and &lt;code&gt;template_name&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;template_path&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;template_path&lt;/code&gt; is for telling Action Mailer which folder to use to look for a template. &lt;code&gt;template_path&lt;/code&gt; can either be a string or an array.&lt;br&gt;
Action Mailer will start looking for the specified &lt;code&gt;template_path&lt;/code&gt; from within &lt;strong&gt;&lt;code&gt;app/views&lt;/code&gt;&lt;/strong&gt; folder. Let's say, our &lt;code&gt;template_path&lt;/code&gt; is set to &lt;code&gt;invitations&lt;/code&gt;. Then, Action Mailer will look for &lt;strong&gt;&lt;code&gt;app/views/invitations&lt;/code&gt;&lt;/strong&gt; folder.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;template_name&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;template_name&lt;/code&gt; is for telling Action Mailer the name of the template that we want to use.&lt;/p&gt;
&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;The first example here shows how we can use a template called &lt;code&gt;welcome&lt;/code&gt; that sits inside of &lt;strong&gt;&lt;code&gt;app/views/mailers/user_mailer/special&lt;/code&gt;&lt;/strong&gt; folder. The &lt;code&gt;template_path&lt;/code&gt; here is a string.&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;UserMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;

    &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;template_path: &lt;/span&gt;&lt;span class="s1"&gt;'mailers/user_mailer/special'&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;The second example here is similar to the above, but &lt;code&gt;template_path&lt;/code&gt; is an array. It's an array of path to folders. Action Mailer will look for the &lt;code&gt;welcome&lt;/code&gt; template by starting on the first folder, &lt;strong&gt;&lt;code&gt;app/views/mailers/user_mailer/non-special&lt;/code&gt;&lt;/strong&gt;. If the template is not found, Action Mailer will move onto the next folder, &lt;strong&gt;&lt;code&gt;app/views/mailers/user_mailer/special&lt;/code&gt;&lt;/strong&gt;, which is where our template sits. Here, Action Mailer will stop looking for the template folder and send the email.&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;UserMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;

    &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;template_path: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'mailers/user_mailer/non-special'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mailers/user_mailer/special'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mailers'&lt;/span&gt;&lt;span class="p"&gt;]&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;The third example here shows how we can use a template called &lt;code&gt;special_welcome&lt;/code&gt; instead of &lt;code&gt;welcome&lt;/code&gt;. &lt;code&gt;special_welcome&lt;/code&gt; sits inside of &lt;strong&gt;&lt;code&gt;app/views/mailers/user_mailer&lt;/code&gt;&lt;/strong&gt; folder&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;UserMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;

    &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;template_name: &lt;/span&gt;&lt;span class="s1"&gt;'special_welcome'&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;The fourth example here shows that we can specify both &lt;code&gt;template_name&lt;/code&gt; and &lt;code&gt;template_path&lt;/code&gt;! This will look for a template called &lt;code&gt;special_welcome&lt;/code&gt; inside of &lt;strong&gt;&lt;code&gt;app/views/mailers/user_mailer/international_launch&lt;/code&gt;&lt;/strong&gt; folder.&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;UserMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;

    &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;template_name: &lt;/span&gt;&lt;span class="s1"&gt;'special_welcome'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;template_path: &lt;/span&gt;&lt;span class="s1"&gt;'mailers/user_mailer/international_launch'&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;The fifth and last example here shows that we can specify the name and location of the template by passing a block to the &lt;code&gt;mail&lt;/code&gt; function. Within the block, we can determine what to render for &lt;code&gt;html&lt;/code&gt;, which is basically the content of the email.&lt;br&gt;&lt;br&gt;
One of the keyword arguments accepted by &lt;code&gt;render&lt;/code&gt; is &lt;code&gt;template&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;UserMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;

    &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;template: &lt;/span&gt;&lt;span class="s1"&gt;'mailers/user_mailer/international_launch/special-welcome'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&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;h2&gt;
  
  
  Specifying a Layout
&lt;/h2&gt;

&lt;p&gt;Another keyword argument accepted by &lt;code&gt;render&lt;/code&gt; is &lt;code&gt;layout&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;The example here shows how we can use a layout called &lt;code&gt;yet-another-layout&lt;/code&gt;. Action Mailer will look for the layout from within &lt;strong&gt;&lt;code&gt;app/layouts&lt;/code&gt;&lt;/strong&gt; folder.&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;UserMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;

    &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&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;layout: &lt;/span&gt;&lt;span class="s1"&gt;'yet-another-layout'&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;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Specifying both the layout and template at once
&lt;/h2&gt;

&lt;p&gt;Yup! We can specify both of them. 😉&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;The example here will use a layout called &lt;code&gt;yet-another-layout&lt;/code&gt; in &lt;strong&gt;&lt;code&gt;app/layouts&lt;/code&gt;&lt;/strong&gt; folder and a template called &lt;code&gt;yet-another-template&lt;/code&gt; in &lt;strong&gt;&lt;code&gt;app/views/mailers&lt;/code&gt;&lt;/strong&gt; folder.&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;UserMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;

    &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;layout: &lt;/span&gt;&lt;span class="s1"&gt;'yet-another-layout'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;template: &lt;/span&gt;&lt;span class="s1"&gt;'mailers/yet-another-template'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&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;Cheers for reading! 🤓&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>8 Things I Have Learned After 2 Years of Work</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Mon, 06 Apr 2020 17:16:45 +0000</pubDate>
      <link>https://dev.to/thealiilman/8-things-i-have-learned-after-2-years-of-work-5cfl</link>
      <guid>https://dev.to/thealiilman/8-things-i-have-learned-after-2-years-of-work-5cfl</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://ali-ilman.com/blog/8-things-i-have-learned-after-2-years-of-work"&gt;https://ali-ilman.com/blog/8-things-i-have-learned-after-2-years-of-work&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It has been two years since I started working as a software engineer. Prior to that, I had been an intern for 3 months at &lt;a href="https://surialabs.com"&gt;the company I've been working for&lt;/a&gt;. There's more to being a software engineer than just writing code and pushing to GitHub repositories.&lt;br&gt;
In this article, I'll be sharing some of the things that have helped me become a better software engineer and a better person, tips that you can apply or serve as a base for you to achieve your goals, and things I only realise after I started working. 🧠&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The internet is your best friend
&lt;/h2&gt;

&lt;p&gt;No matter how experienced you are, you will always end up browsing the web looking for a method name. And this is all right! No one knows everything, and no one remembers everything. What's important is that you understand what you're doing with the code. Through this, I realised that &lt;em&gt;googling&lt;/em&gt; is a skill.&lt;br&gt;
And yes, using StackOverflow isn't cheating. Don't be like me who thought it's cheating to use StackOverflow. 🤦‍♂️&lt;/p&gt;

&lt;h2&gt;
  
  
  2. You will learn on-the-job
&lt;/h2&gt;

&lt;p&gt;There will be methods, classes and libraries you've never used or heard of. Imagine a feature where you can use a library called &lt;em&gt;XYZ&lt;/em&gt; to aid the implementation, but you never heard of &lt;em&gt;XYZ&lt;/em&gt; before. Start by going through the documentation and playing around with the library. Then, use it to implement the feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Get involved with the community
&lt;/h2&gt;

&lt;p&gt;Is Ruby the main programming language that you use? Are you a React wizard? There are meetups for people who use or are curious about these technologies! You get to meet like-minded people and make new connections, you get to gain knowledge from talks. And if you've something to share, you can always get in touch with the organisers and tell them that you're interested in giving a talk. It's good to give back.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Don't get too excited to implement a feature or a bug fix
&lt;/h2&gt;

&lt;p&gt;It's easy to feel excited to start working on a feature or a bug fix when it's ready to be implemented. This can be a misconception of what you should be doing as you're eager to get going. Instead, try to understand what needs to be done, and think how this can be implemented in the cleanest way possible.&lt;br&gt;
Keep in mind that it's easy to overthink about keeping the code clean as there are many ways to implement something, so don't waste too much time on this. We could ask our teammates for their opinions, and there are always code reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Don't be aggressive in code reviews
&lt;/h2&gt;

&lt;p&gt;One of the things I've learned about code reviews is to not approach them aggressively. This can be in your choice of words and / or the intonation of your words. Remember, a code review isn't just for tidying up code. A code review is also a way for you and the author of the code to improve as engineers. Build each other up. 💪&lt;br&gt;
A personal rule of mine is to not use GitHub's &lt;em&gt;Request changes&lt;/em&gt; when submitting a review. I feel it can make the person who wrote the code feel less confident or make their suffering of &lt;a href="https://flaviocopes.com/imposter-syndrome/"&gt;imposter syndrome&lt;/a&gt; even worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Ensure that your pull requests are descriptive
&lt;/h2&gt;

&lt;p&gt;There will be bug fixes, enhancements and features being implemented. Writing a descriptive pull request will give the reviewers the context of the pull request, which can result in effective improvements to the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Self-care is important
&lt;/h2&gt;

&lt;p&gt;One of the topics I've seen people talk about is whether you should code in your free time.&lt;br&gt;
Can working on side projects in your free time help you become a better engineer? Yup. But should you be doing this? This is for you to decide. Only you know your body well. A good rest is important. And most importantly, don't forget to spend time with your loved ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Build up fellow engineers
&lt;/h2&gt;

&lt;p&gt;Remember, always stay humble. It's easy to let your knowledge negatively control your behaviour. Use your knowledge to build up fellow engineers. 🙂 I encourage you to check out &lt;a href="https://buildupdevs.com/"&gt;BuildUpDevs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope this article has given you an idea of how it's like to work in the tech industry. Feel free to ask me questions!  &lt;/p&gt;

&lt;p&gt;Cheers for reading! 🤓&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I share the life of a software engineer on &lt;a href="https://twitter.com/thealiilman"&gt;Twitter&lt;/a&gt;, you might want to follow me.&lt;/em&gt; 😉&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>4 Mistakes I Made When I First Learned How To Code</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Mon, 30 Mar 2020 15:41:40 +0000</pubDate>
      <link>https://dev.to/thealiilman/4-mistakes-i-made-when-i-first-learned-how-to-code-56go</link>
      <guid>https://dev.to/thealiilman/4-mistakes-i-made-when-i-first-learned-how-to-code-56go</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://ali-ilman.com/blog/4-mistakes-i-made-when-i-first-learned-how-to-code"&gt;https://ali-ilman.com/blog/4-mistakes-i-made-when-i-first-learned-how-to-code&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With my two-year anniversary of working permanently coming soon, I took a look into the past and thought of what were the mistakes that I made in the very beginning.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Let completing a course influence how I feel
&lt;/h2&gt;

&lt;p&gt;I was a &lt;em&gt;course champion&lt;/em&gt; in the beginning. It felt good knowing that I have completed a course, but I kept going through courses without an idea of which path I wanted to take in the tech industry. I had completed courses on Codecademy and SoloLearn, a couple of tutorials on freeCodeCamp, and the courses were sort of similar.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Not writing down notes in my own words
&lt;/h2&gt;

&lt;p&gt;Instead of using my own words, which can test myself on whether I understand what I've learned, I wrote down courses' content word-for-word, including the exemplary code snippets! And I did this for more than a few courses on a few platforms. Ouch!&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Not going in-depth with concepts I found difficult to understand
&lt;/h2&gt;

&lt;p&gt;I feel this go hand-in-hand with number 1. It felt good completing a challenge for a tutorial, so I continued onto the next tutorial without thinking deeply whether I understand what I've learned.&lt;br&gt;
Because of this, I &lt;em&gt;relearned&lt;/em&gt; JavaScript in the second-half of 2019 because I mostly learned JavaScript in the beginning.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Built barely anything with what I've learned
&lt;/h2&gt;

&lt;p&gt;When I first started learning, I didn't build much in the first 2-3 years. I can only remember two projects, and they were on Codecademy. For these two projects, I had wanted to mimic the landing page of &lt;a href="https://twitter.com"&gt;Twitter&lt;/a&gt; and &lt;a href="https://www.lowyat.net/"&gt;Lowyat&lt;/a&gt;. And that's about it. It was only in 2017 in which I started to build projects.&lt;/p&gt;

&lt;p&gt;Finishing a course doesn't mean you understand everything you've went through. And remember, learning is lifelong. 🧠 &lt;/p&gt;

&lt;p&gt;&lt;em&gt;The only true wisdom is in knowing you know nothing. - Socrates&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Cheers for reading! 🤓&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I share the rumblings of a Man United fan and the life of a software engineer on &lt;a href="https://twitter.com/thealiilman"&gt;Twitter&lt;/a&gt;, you might want to follow me.&lt;/em&gt; 😉&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Profiling and Speeding Up Our Rails Test Suite with TestProf</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Sun, 22 Mar 2020 13:49:13 +0000</pubDate>
      <link>https://dev.to/thealiilman/profiling-and-speeding-up-our-rails-test-suite-with-testprof-37c9</link>
      <guid>https://dev.to/thealiilman/profiling-and-speeding-up-our-rails-test-suite-with-testprof-37c9</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://ali-ilman.com/blog/profiling-and-speeding-up-our-rails-test-suite-with-test-prof"&gt;https://ali-ilman.com/blog/profiling-and-speeding-up-our-rails-test-suite-with-test-prof&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;RSpec best practices can only go so far in speeding up our test suite. Are you looking to speed up your Rails test suite? You've come to the right place! In this article, we'll take a look at &lt;a href="https://github.com/palkan/test-prof"&gt;TestProf&lt;/a&gt;, a Ruby gem that provides profilers for analysing our test suite, and helpers to improve the test suite's performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  How did I end up using TestProf?
&lt;/h2&gt;

&lt;p&gt;A month ago, I gave a go at speeding up the test suite of a project I'm working on. For a bit of background, the project's codebase is almost 6 years old, developers have come and go, new technologies and practices have appeared after all these years. We had a sprint where we can make our lives easier, in other words, enhance the codebase! And we decided speeding up the test suite was one of them. 🕵️‍♂️&lt;/p&gt;

&lt;p&gt;The test suite took around 45 minutes (!) to run on my Mac. That's horrendous! 😭 Initially, I applied practices (which you can read about &lt;a href="https://dev.to/thealiilman/3-practices-to-apply-to-speed-up-our-rails-test-suite-12p0"&gt;here&lt;/a&gt;) that can speed up the test suite, but the improvement was little. It was clear that something else is making the test suite take longer than usual. And that's when I decided to add TestProf to the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the common causes of a lengthy test suite?
&lt;/h2&gt;

&lt;p&gt;There are a few common causes, and the most common cause is arguably the &lt;strong&gt;&lt;em&gt;factory usage&lt;/em&gt;&lt;/strong&gt;. And what is a factory?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A factory generates test data that are used in tests. These data can be an Active Record object, a plain Ruby object and so on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Factory usage can negatively affect the performance of the test suite because of these two reasons.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Creation of records for each test
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Wait a minute. Don't we sometimes need to seed our database before running our tests?&lt;/em&gt;&lt;br&gt;&lt;br&gt;
Yup, that's correct. But wouldn't it be great if we can create one single record for the entire test file? Let's take a look at the example below. 🤓&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="c1"&gt;# factories/books.rb&lt;/span&gt;
&lt;span class="no"&gt;FactoryBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:book&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&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;span class="c1"&gt;# requests/books_controller_spec.rb&lt;/span&gt;
&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;BooksController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :request&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'GET #show'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;book_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'DELETE #destroy'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;book_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt;
    &lt;span class="k"&gt;end&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;As we can see in the code above, the &lt;code&gt;book&lt;/code&gt; variable is invoked for each test (&lt;code&gt;it&lt;/code&gt;), which means we're telling the &lt;code&gt;book&lt;/code&gt; factory to create a &lt;code&gt;book&lt;/code&gt; for &lt;strong&gt;each test&lt;/strong&gt;! This is unnecessary for the tests above.&lt;br&gt;&lt;br&gt;
Can't we initialize a &lt;code&gt;@book&lt;/code&gt; variable inside of a &lt;code&gt;before(:all)&lt;/code&gt; to create a record just once? 🤔 We can, but &lt;code&gt;before(:all)&lt;/code&gt; doesn't wrap the tests within a transaction, so nothing is rolled back after they have been ran.&lt;br&gt;
We'll see later on in the article how a TestProf helper allows us to create a record only once &lt;strong&gt;and&lt;/strong&gt; without going through the headache of cleaning our test database.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Nested factory invocations
&lt;/h3&gt;

&lt;p&gt;Nested factory invocations can cause &lt;em&gt;factory cascades&lt;/em&gt;.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A factory cascade is a term given to the process of creating new associated objects inside of each factory through nested factory invocations. 🧠&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's an example of factory cascades, copied mostly from &lt;a href="https://test-prof.evilmartians.io/#/factory_default"&gt;test-prof's documentation&lt;/a&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="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:account&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;account&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:project&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;account&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:task&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;account&lt;/span&gt;
  &lt;span class="n"&gt;project&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is happening when we tell FactoryBot to create a task?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The task's &lt;code&gt;account&lt;/code&gt; is created&lt;/li&gt;
&lt;li&gt;The task's &lt;code&gt;project&lt;/code&gt; is created, followed by the project's &lt;code&gt;account&lt;/code&gt; and &lt;code&gt;user&lt;/code&gt;, followed by the user's &lt;code&gt;account&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The task's &lt;code&gt;user&lt;/code&gt; is created, followed by the user's &lt;code&gt;account&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In overall, four accounts are created even though all we need is one account.&lt;/p&gt;

&lt;p&gt;Here's an example of simple nested factory invocations.&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="c1"&gt;# factories/publishers.rb&lt;/span&gt;
&lt;span class="no"&gt;FactoryBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:publisher&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Company&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&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;span class="c1"&gt;# factories/authors.rb&lt;/span&gt;
&lt;span class="no"&gt;FactoryBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:author&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;author&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;publisher&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# factories/books.rb&lt;/span&gt;
&lt;span class="no"&gt;FactoryBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:book&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;author&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;If we were to use the &lt;code&gt;book&lt;/code&gt; factory to create a book, it'll invoke the &lt;code&gt;author&lt;/code&gt; factory, which in turn will invoke the &lt;code&gt;publisher&lt;/code&gt; factory! Do we really need a publisher and an author for all tests? Not really, because some tests can be written with record(s) from only one single model, which in our case is the &lt;code&gt;Book&lt;/code&gt; model.&lt;/p&gt;

&lt;p&gt;One of the reasons why a factory is used is to help generate data for associations, but at the same time, this can come at the cost of unnecessary factory usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can TestProf help us improve our test suite?
&lt;/h2&gt;

&lt;p&gt;TestProf comes with various of profilers and helpers, but in this article, I'm only going to share the ones that can make a significant improvement to the test suite and the ones that I've utilised. Let's start with the profilers!&lt;/p&gt;

&lt;h3&gt;
  
  
  1. FactoryDoctor
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;FactoryDoctor&lt;/em&gt; will go through our test suite for any tests that perform unnecessary database queries.&lt;br&gt;
Here's an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FDOC=1 rspec spec/services/books/update_availability_spec.rb


Total (potentially) bad examples: 1
Total wasted time: 00:00.018

Book (./spec/models/book_spec.rb:3) (2 records created, 00:00.018)
  is expected to validate that :title cannot be empty/falsy (./spec/models/book_spec.rb:10) – 2 records created, 00:00.018

Finished in 0.12646 seconds (files took 1.18 seconds to load)
2 examples, 0 failures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also make FactoryDoctor ignore a test, by adding &lt;code&gt;:fd_ignore&lt;/code&gt; to the test.&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="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'.published'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;described_class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;published&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:fd_ignore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;([])&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;There's one thing to be wary of when using FactoryDoctor, though. There's a chance that it'll report false positives and false negatives as it's still learning, so don't always trust it. Dig deeper into certain tests if you're looking to eliminate unnecessary database queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. FactoryProf
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;FactoryProf&lt;/em&gt; will analyse our factory usage, and after the tests have finished running, it'll display the following report.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FPROF=1 rspec spec/services/books/update_availability_spec.rb

Finished in 21.08 seconds (files took 1.15 seconds to load)
3 examples, 0 failures

[TEST PROF INFO] Factories usage

 Total: 6
 Total top-level: 6
 Total time: 0.0515s
 Total uniq factories: 2

   total   top-level     total time      time per call      top-level time               name

       3           3        0.0304s            0.0101s             0.0304s             author
       3           3        0.0211s            0.0070s             0.0211s               book
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does the report show?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The number of times factories were invoked&lt;/li&gt;
&lt;li&gt;The number of times factories were invoked (excluding nested factory invocations)&lt;/li&gt;
&lt;li&gt;The time spent generating records&lt;/li&gt;
&lt;li&gt;The number of factories, in our case is 2 for &lt;code&gt;author&lt;/code&gt; and &lt;code&gt;book&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You will love FactoryProf. I was utterly astounded to see the report for the project I work on, I found out that we spent 36 minutes just for generating records! 🤯&lt;/p&gt;

&lt;p&gt;Let's move on to the helpers.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. FactoryDefault
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;FactoryDefault&lt;/em&gt; helps with eliminating factory cascades by reusing associated records.&lt;br&gt;
Going back to the factory cascades example, we can use FactoryDefault's &lt;code&gt;create_default&lt;/code&gt; to reuse associated records.&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;factory&lt;/span&gt; &lt;span class="ss"&gt;:account&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;account&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:project&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;account&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:task&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;account&lt;/span&gt;
  &lt;span class="n"&gt;project&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;create_default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is happening here?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An &lt;code&gt;account&lt;/code&gt; is created and the same object is reused for &lt;code&gt;user&lt;/code&gt;, &lt;code&gt;project&lt;/code&gt; and &lt;code&gt;task&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The task's &lt;code&gt;account&lt;/code&gt; will refer to the one created with &lt;code&gt;create_default&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The task's &lt;code&gt;project&lt;/code&gt; is created, followed by the reusing of the &lt;code&gt;account&lt;/code&gt;, and the creation of &lt;code&gt;user&lt;/code&gt;, followed again by the reusing of the &lt;code&gt;account&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The task's &lt;code&gt;user&lt;/code&gt; is created, followed by the reusing of the &lt;code&gt;account&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In overall, only &lt;strong&gt;one&lt;/strong&gt; account is created.&lt;/p&gt;

&lt;p&gt;Do be careful with using FactoryDefault, as it can reduce the readability of your tests. 👁&lt;/p&gt;

&lt;h3&gt;
  
  
  2. before_all
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;before_all&lt;/code&gt; is similar to RSpec’s &lt;code&gt;before(:all)&lt;/code&gt;. The only difference is that when we use &lt;code&gt;before_all&lt;/code&gt;, it wraps the tests within a transaction, thus destroying the records afterwards. For RSpec’s &lt;code&gt;before(:all)&lt;/code&gt;, we have to destroy the records ourselves through &lt;code&gt;after(:all)&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Before
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:all&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;# test&lt;/span&gt;
  &lt;span class="c1"&gt;# test&lt;/span&gt;
  &lt;span class="c1"&gt;# test&lt;/span&gt;

  &lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:all&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy_all&lt;/span&gt;
    &lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy_all&lt;/span&gt;
    &lt;span class="no"&gt;Publisher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy_all&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;h4&gt;
  
  
  After
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;before_all&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;# test&lt;/span&gt;
  &lt;span class="c1"&gt;# test&lt;/span&gt;
  &lt;span class="c1"&gt;# test&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps our tests tidy. 🤓&lt;/p&gt;

&lt;h3&gt;
  
  
  3. let_it_be
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;let_it_be&lt;/code&gt; works similarly to &lt;code&gt;before_all&lt;/code&gt;, with the addition of allowing us to use variables.&lt;/p&gt;

&lt;h4&gt;
  
  
  Before
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# requests/books_controller_spec.rb&lt;/span&gt;
&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;BooksController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :request&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'GET #show'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;book_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'DELETE #destroy'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;book_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt;
    &lt;span class="k"&gt;end&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;&lt;code&gt;book&lt;/code&gt; is invoked twice, thus creating two book records.&lt;/p&gt;

&lt;h4&gt;
  
  
  After
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# requests/books_controller_spec.rb&lt;/span&gt;
&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;BooksController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :request&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let_it_be&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'GET #show'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;book_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'DELETE #destroy'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;book_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_http_status&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt;
    &lt;span class="k"&gt;end&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;&lt;code&gt;book&lt;/code&gt; is invoked twice but only &lt;strong&gt;one&lt;/strong&gt; book record is created.&lt;/p&gt;

&lt;p&gt;There is one &lt;strong&gt;caveat&lt;/strong&gt; with using &lt;code&gt;let_it_be&lt;/code&gt;.&lt;br&gt;
If we were to a modify record generated within a &lt;code&gt;let_it_be&lt;/code&gt; outside of &lt;code&gt;let_it_be&lt;/code&gt;, we need to &lt;em&gt;reload&lt;/em&gt; or &lt;em&gt;re-find&lt;/em&gt; the record. The cost of reloading or querying for a record is still less than generating one.&lt;/p&gt;

&lt;h4&gt;
  
  
  Before
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let_it_be&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'#update'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when title is valid'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:new_title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;'And Then There Were None'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;book&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="ss"&gt;title: &lt;/span&gt;&lt;span class="n"&gt;new_title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; false&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&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;h4&gt;
  
  
  After
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :model&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# let_it_be(:book, refind: true) { create(:book) }&lt;/span&gt;
  &lt;span class="n"&gt;let_it_be&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;reload: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'#update'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when title is valid'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:new_title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;'And Then There Were None'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;book&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="ss"&gt;title: &lt;/span&gt;&lt;span class="n"&gt;new_title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&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;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Using TestProf can help speed up your test suite massively. Benchmark your test suite by utilising the profilers that come with the gem, though you might find FactoryProf and FactoryDoctor become your go-to profilers. Then, identify the slowest tests, and try to determine the tests that can gain significant improvement in speed when helpers provided by TestProf are used. Performant tests are a nice-to-have, but don't forget, keep the tests readable.&lt;/p&gt;

&lt;p&gt;Cheers for reading and I hope you find this article helpful! 🤓&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>testing</category>
    </item>
    <item>
      <title>3 Practices to Apply to Speed Up Our Rails Test Suite</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Wed, 29 Jan 2020 13:52:05 +0000</pubDate>
      <link>https://dev.to/thealiilman/3-practices-to-apply-to-speed-up-our-rails-test-suite-12p0</link>
      <guid>https://dev.to/thealiilman/3-practices-to-apply-to-speed-up-our-rails-test-suite-12p0</guid>
      <description>&lt;p&gt;When more features are added to our application, the time it takes to run our tests increases. The pain of this is more evident when we work in a team of fellow developers, pushing to the repository and triggering builds on the CI platform multiple times per day! 😭&lt;br&gt;
But don't worry, there are 3 practices we can apply to speed up our test suite!&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Replace &lt;code&gt;let!&lt;/code&gt; variables with &lt;code&gt;let&lt;/code&gt; variables
&lt;/h3&gt;

&lt;p&gt;Why should we replace &lt;code&gt;let!&lt;/code&gt; with &lt;code&gt;let&lt;/code&gt;? How does using &lt;code&gt;let&lt;/code&gt; help speed up our test suite? Let's first take a look at what &lt;code&gt;let!&lt;/code&gt; does behind the scenes. 🕵️‍♂️  &lt;/p&gt;

&lt;p&gt;This is how the &lt;code&gt;let!&lt;/code&gt; method looks like &lt;a href="https://github.com/rspec/rspec-core/blob/e4e10d977320743931b9f4644c37b765d69a5fd6/lib/rspec/core/memoized_helpers.rb#L374"&gt;in rspec-core's codebase&lt;/a&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;def&lt;/span&gt; &lt;span class="nf"&gt;let!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;__send__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&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;As we can see, it basically calls &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;before&lt;/code&gt;. But notice the block passed to &lt;code&gt;before&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="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;__send__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&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 invoke the method which is identified by the &lt;code&gt;name&lt;/code&gt; parameter &lt;strong&gt;before&lt;/strong&gt; each example is run. Let's move onto to an example!  &lt;/p&gt;

&lt;p&gt;This service was written as dumb as possible for the sake of this example. 😁 The service returns books that were fetched from a fictional platform called &lt;em&gt;Bibliothek&lt;/em&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;module&lt;/span&gt; &lt;span class="nn"&gt;Bibliothek&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GetBooks&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;
      &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&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;run&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'And Then There Were None'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;author: &lt;/span&gt;&lt;span class="s1"&gt;'Agatha Christie'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'Far from the Madding Crowd'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;author: &lt;/span&gt;&lt;span class="s1"&gt;'Tom Hardy'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'This Was a Man'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;author: &lt;/span&gt;&lt;span class="s1"&gt;'Jeffrey Archer'&lt;/span&gt;
        &lt;span class="p"&gt;}&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;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we have this spec for the service above.&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;describe&lt;/span&gt; &lt;span class="no"&gt;Bibliothek&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;GetBooks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :service&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'.run'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;let!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:titles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="c1"&gt;# An expensive process&lt;/span&gt;
      &lt;span class="nb"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'And Then There Were None'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Far from the Madding Crowd'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'This Was a Man'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:authors&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;'Agatha Christie'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Tom Hardy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Jeffrey Archer'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;described_class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'has 3 book records'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;titles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;be_a&lt;/span&gt; &lt;span class="no"&gt;Array&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;Even though we're not explicitly invoking &lt;code&gt;titles&lt;/code&gt;, the &lt;code&gt;titles&lt;/code&gt; variable will be evaluated for &lt;strong&gt;each&lt;/strong&gt; example thanks to the way &lt;code&gt;let!&lt;/code&gt; was written.&lt;br&gt;
The time it takes for the entire &lt;code&gt;.run&lt;/code&gt; example group to run is 4 seconds on average!  &lt;/p&gt;

&lt;p&gt;How can we enhance this?&lt;br&gt;&lt;br&gt;
We convert the &lt;code&gt;titles&lt;/code&gt; variable from a &lt;code&gt;let!&lt;/code&gt; into a &lt;code&gt;let&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="n"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;Bibliothek&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;GetBooks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :service&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'.run'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:titles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="c1"&gt;# An expensive process&lt;/span&gt;
      &lt;span class="nb"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'And Then There Were None'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Far from the Madding Crowd'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'This Was a Man'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="c1"&gt;# other code&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, the time it takes is slashed by half! 🎉🎉🎉&lt;br&gt;&lt;br&gt;
The key here is to remember that a &lt;code&gt;let&lt;/code&gt; variable is only evaluated &lt;strong&gt;when we explicitly invoke it&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Write multiple expectations in one single example
&lt;/h3&gt;

&lt;p&gt;Sometimes, it's unnecessary to write an example (&lt;code&gt;it&lt;/code&gt;) for each expectation (&lt;code&gt;expect&lt;/code&gt;, &lt;code&gt;should&lt;/code&gt; etc.).&lt;br&gt;&lt;br&gt;
Although it's cleaner (who doesn't love short one-liners? 😍),&lt;br&gt;
it can affect the performance of our tests.&lt;br&gt;
How?  &lt;/p&gt;

&lt;p&gt;Say, we have a service that updates the availability of a book.&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;module&lt;/span&gt; &lt;span class="nn"&gt;Books&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UpdateAvailability&lt;/span&gt;
    &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:book&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vi"&gt;@book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;run&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;run&lt;/span&gt;
      &lt;span class="c1"&gt;# An expensive process&lt;/span&gt;
      &lt;span class="nb"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;book&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="ss"&gt;available: &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;OpenStruct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;success?: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;book: &lt;/span&gt;&lt;span class="n"&gt;book&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;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we have this spec.&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;describe&lt;/span&gt; &lt;span class="no"&gt;Books&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;UpdateAvailability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :service&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'.run'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'And Then There Were None'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;available: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;author: &lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Agatha Christie'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;described_class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;success?&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;available&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="kp"&gt;false&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;The time it takes on average is a staggering 10 seconds! Why is this the case?&lt;br&gt;&lt;br&gt;
The subject is executed for each example, in our case being 2 examples. This is unnecessary, and it makes no sense for us to separate the expectations when they're clearly related to the data returned by &lt;code&gt;described_class.run(book)&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;What can we do? It's simple. We group all expectations in one example.&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;describe&lt;/span&gt; &lt;span class="no"&gt;Books&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;UpdateAvailability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :service&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'.run'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="ss"&gt;:book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'And Then There Were None'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;available: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;author: &lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Agatha Christie'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;described_class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;success?&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;available&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
    &lt;span class="k"&gt;end&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;This will reduce the time taken by half! 🎉🎉🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Use &lt;code&gt;build_stubbed&lt;/code&gt; when persisted objects aren't required for the test
&lt;/h3&gt;

&lt;p&gt;There are times when the tests we write do not require us to use persisted objects. And that's when we realise we should use &lt;code&gt;build_stubbed&lt;/code&gt; instead of &lt;code&gt;build&lt;/code&gt; or &lt;code&gt;create&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;build_stubbed&lt;/code&gt; will stub out methods relevant to persistence. In other words, you won't be able to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Test the persistence of an object.&lt;/li&gt;
&lt;li&gt;Test the callbacks that should execute after updating an object.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are the methods excluded from the stubbed object returned by &lt;code&gt;build_stubbed&lt;/code&gt;. (&lt;a href="https://github.com/thoughtbot/factory_bot/blob/5a3247dd8c77e8ae98c4d1586726e382b143406c/lib/factory_bot/strategy/stub.rb#L6"&gt;retrieved via factory_bot's code base&lt;/a&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="no"&gt;DISABLED_PERSISTENCE_METHODS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="ss"&gt;:connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:decrement!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:delete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:destroy!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:destroy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:increment!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:reload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:save!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:save&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:toggle!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:touch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:update!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:update_attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:update_attributes!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:update_attributes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:update_column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:update_columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;These three simple practices allow our test suite to run faster, but the gains varies. If we've not applied the first two practices, then the more complex and larger the codebase is, the more the amount of gains we can extract. But don't expect any massive gains from using &lt;code&gt;build_stubbed&lt;/code&gt;! 😝&lt;/p&gt;

&lt;p&gt;If you want to take a look at the code, feel free to visit &lt;a href="https://github.com/thealiilman/bessere-leistung/"&gt;the repository&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Cheers for reading and I hope you find this article helpful! 🤓&lt;br&gt;
Please leave your comments below if you have any questions / thoughts or if you know of other practices we can apply to speed up our Rails test suite. ✌️&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>testing</category>
    </item>
    <item>
      <title>A Look into Discard</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Mon, 02 Sep 2019 12:41:05 +0000</pubDate>
      <link>https://dev.to/thealiilman/a-look-into-discard-jf2</link>
      <guid>https://dev.to/thealiilman/a-look-into-discard-jf2</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="//ali-ilman.com/blog"&gt;ali-ilman.com/blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, we want to soft delete specific records in our app.&lt;br&gt;
What is a soft delete?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A soft delete is a term for flagging a record in the DB as deleted. A use case for this is when you want it to be hidden from the public but visible to the admin for record purposes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the world of Rails, there are various ways you can do that. You can write your own soft delete feature or you can use a gem such as discard.&lt;/p&gt;
&lt;h2&gt;
  
  
  A Look Into Discard
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/jhawthorn/discard"&gt;Discard&lt;/a&gt; is a gem created by John Hawthorn, describing the gem as &lt;em&gt;soft deletes for ActiveRecord done right&lt;/em&gt;. The gem is basically a &lt;em&gt;simple ActiveRecord mixin to add conventions for flagging records as discarded&lt;/em&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Setup
&lt;/h4&gt;

&lt;p&gt;For this example, I'll create an app where there are authors, books and publishers tables.&lt;br&gt;
An &lt;code&gt;Author&lt;/code&gt; can have many &lt;code&gt;Books&lt;/code&gt;, a &lt;code&gt;Publisher&lt;/code&gt; can have many &lt;code&gt;Authors&lt;/code&gt;, and a &lt;code&gt;Publisher&lt;/code&gt; can have many &lt;code&gt;Books&lt;/code&gt; through &lt;code&gt;Authors&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;Author&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;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:publisher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;optional: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:books&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dependent: :nullify&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Book&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;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:author&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Publisher&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_many&lt;/span&gt; &lt;span class="ss"&gt;:authors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dependent: :nullify&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:books&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :authors&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Add this into your gemfile and then run &lt;code&gt;bundle&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'discard'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 1.0'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For the record that you want to be discardable, in our case, &lt;code&gt;Author&lt;/code&gt;, include discard in the author model like so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;Author&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="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Discard&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Model&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, you generate a migration to add the relevant attributes to the &lt;em&gt;authors&lt;/em&gt; table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails generate migration add_discarded_at_to_authors discarded_at:datetime:index
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  How to discard a record
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;discard&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;discarded_at&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; Sun, 01 Sep 2019 10:48:31 UTC +00:00&lt;/span&gt;
&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;discarded?&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  How to undiscard a record
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;undiscard&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;discarded_at&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;discarded?&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Accessing records
&lt;/h4&gt;

&lt;p&gt;Discard adds the following 4 methods for the discardable record.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_discarded&lt;/span&gt; &lt;span class="c1"&gt;# an alias for Author.all&lt;/span&gt;
&lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;kept&lt;/span&gt; &lt;span class="c1"&gt;# returns a collection of undiscarded authors&lt;/span&gt;
&lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;discarded&lt;/span&gt; &lt;span class="c1"&gt;# returns a collection of discarded authors&lt;/span&gt;
&lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;undiscarded&lt;/span&gt; &lt;span class="c1"&gt;# an alias for Author.kept&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Callbacks?!?!?!
&lt;/h4&gt;

&lt;p&gt;Discard adds &lt;code&gt;before_&lt;/code&gt;, &lt;code&gt;around_&lt;/code&gt; and &lt;code&gt;after_&lt;/code&gt; callbacks for you to utilise if needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;Author&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="o"&gt;...&lt;/span&gt;
  &lt;span class="n"&gt;before_discard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'Hallo before_discard!'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;after_discard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'after_discard!'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;before_undiscard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'Waving at you before_undiscard...'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;after_undiscard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'Yay after_undiscard!'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;discard&lt;/span&gt;
&lt;span class="c1"&gt;# other logs&lt;/span&gt;
&lt;span class="no"&gt;Hallo&lt;/span&gt; &lt;span class="n"&gt;before_discard!&lt;/span&gt;
&lt;span class="c1"&gt;# other logs&lt;/span&gt;
&lt;span class="n"&gt;after_discard!&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;undiscard&lt;/span&gt;
&lt;span class="c1"&gt;# other logs&lt;/span&gt;
&lt;span class="no"&gt;Waving&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;before_undiscard&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="c1"&gt;# other logs&lt;/span&gt;
&lt;span class="no"&gt;Yay&lt;/span&gt; &lt;span class="n"&gt;after_undiscard!&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Unfortunately though, the &lt;code&gt;around_&lt;/code&gt; callbacks don't seem to work. An example would be, &lt;code&gt;Author.first.discard&lt;/code&gt;. It'll query for the author and run the code in &lt;code&gt;around_discard&lt;/code&gt; but it won't discard the author. It may be a bug within the gem. 🤔&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;Discard removes the magic that comes with alternatives such as &lt;a href="https://github.com/rubysherpas/paranoia"&gt;paranoia&lt;/a&gt; and &lt;a href="https://github.com/ActsAsParanoid/acts_as_paranoid"&gt;acts_as_paranoid&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've used paranoia on a few projects, and one of them's a project of a decent size. I remember initially making most models &lt;em&gt;paranoid&lt;/em&gt;. We encountered issues, one of them being a &lt;code&gt;has_many dependent: :destroy&lt;/code&gt; association. Those dependent records needed to be paranoid as well, otherwise the records will be destroyed for good. 😱 Another issue is that, although I can't exactly call it, one of the records has a has_many_ association and it was searching for a soft-deleted record using an &lt;code&gt;id&lt;/code&gt; that still exist within the collection, but the said record with the existing &lt;code&gt;id&lt;/code&gt; couldn't be found! 🤯&lt;/p&gt;

&lt;p&gt;One might argue that discard goes against &lt;em&gt;convention over configuration&lt;/em&gt;, which is one of the principles of Rails, and can add verbosity to the codebase. An example would be, you'd have to keep on adding &lt;code&gt;.kept&lt;/code&gt; to a model or an association to access a collection of undiscarded records. But personally, it's easy to setup and use. Plus unlike the other two gems, discard doesn't change the model's default_scope. I suggest you to go with discard to avoid possible long-term pain. 😉&lt;/p&gt;

&lt;p&gt;You can check out the code for the app above &lt;a href="https://github.com/thealiilman/loeschen"&gt;here&lt;/a&gt; where you can select different branches to view the implementation with &lt;a href="https://github.com/thealiilman/loeschen/tree/feature/soft-delete-with-discard"&gt;discard&lt;/a&gt; or &lt;a href="https://github.com/thealiilman/loeschen/tree/feature/soft-delete-with-paranoia"&gt;paranoia&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why Do You Write Code?</title>
      <dc:creator>Ali Ilman</dc:creator>
      <pubDate>Sat, 29 Jun 2019 17:31:55 +0000</pubDate>
      <link>https://dev.to/thealiilman/why-do-you-write-code-mhm</link>
      <guid>https://dev.to/thealiilman/why-do-you-write-code-mhm</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://ali-ilman.com/blog/"&gt;ali-ilman.com/blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I recently read an Instagram &lt;a href="https://www.instagram.com/p/BzNcYFxgwCf/"&gt;post&lt;/a&gt; by a fellow programmer. There's a question in the post, which is &lt;em&gt;why do you code / program&lt;/em&gt;. Whenever I read such question, the first thing that pops into my mind would be, &lt;em&gt;the satisfaction in seeing the code you wrote brings a product to life&lt;/em&gt;.  &lt;/p&gt;

&lt;p&gt;I remember starting out on &lt;a href="https://www.khanacademy.org/"&gt;Khan Academy&lt;/a&gt; back in May 2014. Oh Lord, it feels like that was yesterday. 😱 I can't recall exactly what I learned on Khan Academy, but I believe it was Drawing &amp;amp; Animation in JavaScript. I'm not sure why I started with Drawing &amp;amp; Animation. To be quite honest about it, I hated it! 😂&lt;br&gt;
I didn't finish the course either, and I never liked drawing anyway when I went to school. Plus the course felt rather advanced for a beginner, or it could be me being oblivious to there being more beginner-friendly courses. 🤷‍♂️ After Khan Academy, I learned on Codecademy, freeCodeCamp, SoloLearn. It was mostly JavaScript tutorials. I never really got going after each of the fundamental JavaScript courses on each platform. I was trapped in-between the &lt;em&gt;after tutorial&lt;/em&gt; and the &lt;em&gt;creating projects&lt;/em&gt; phases. Having known myself more, I find that Udemy courses give me those &lt;em&gt;Oh I see!&lt;/em&gt; moments. If only I discovered the platform much earlier!&lt;/p&gt;

&lt;p&gt;But two things stuck with me, and they are the excitement in creating something and knowing that you can create almost, if not, anything, with code. One can solve a problem for society, improvise on something for fellow developers and many more!&lt;/p&gt;

&lt;p&gt;Fast forward to 2019, I've been working for a year &amp;amp; a half. Including the reasons above, why do I write code?  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Excitement in creating something.&lt;/li&gt;
&lt;li&gt;Knowing that you can create almost, if not, anything, with code, and contribute to society in such way.&lt;/li&gt;
&lt;li&gt;The satisfaction in seeing the code you wrote brings a product to life.&lt;/li&gt;
&lt;li&gt;Writing code is a piece of art. Clean, readable code is utter beauty, poetry-esque!&lt;/li&gt;
&lt;li&gt;Solving code problems are satisfying.&lt;/li&gt;
&lt;li&gt;The flexibility in being able to work from basically anywhere.&lt;/li&gt;
&lt;li&gt;The demand for programmers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;How about you? Why do you write code? 🤓&lt;/p&gt;

</description>
      <category>programming</category>
      <category>career</category>
      <category>webdev</category>
      <category>dev</category>
    </item>
  </channel>
</rss>
