<?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>Forem: lucasprag</title>
    <description>The latest articles on Forem by lucasprag (@lucasprag).</description>
    <link>https://forem.com/lucasprag</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%2F56888%2F3f4d82d0-be3a-4f76-b526-f0c2d2623a4b.png</url>
      <title>Forem: lucasprag</title>
      <link>https://forem.com/lucasprag</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lucasprag"/>
    <language>en</language>
    <item>
      <title>Underrated VSCode feature: Native Tabs</title>
      <dc:creator>lucasprag</dc:creator>
      <pubDate>Thu, 18 Apr 2024 21:48:56 +0000</pubDate>
      <link>https://forem.com/lucasprag/underrated-vscode-feature-native-tabs-3bl</link>
      <guid>https://forem.com/lucasprag/underrated-vscode-feature-native-tabs-3bl</guid>
      <description>&lt;p&gt;At work, I often have to make changes to many repository-based projects at the same time. They can be multiple back-end projects, multiple front-end projects, documentation, infra as code, etc.&lt;/p&gt;

&lt;p&gt;With so many projects, I used to often struggle with many VSCode windows.&lt;/p&gt;

&lt;p&gt;I tried working with VSCode Workspaces, but they didn’t really click for me.&lt;/p&gt;

&lt;p&gt;However, there is a feature called Native Tabs that allows me to group all my VSCode windows together and move between them easily. Notice how each project is in a different tab:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  How to setup Native Tabs
&lt;/h2&gt;

&lt;p&gt;Look for Native Tabs on Settings or add &lt;code&gt;"window.nativeTabs": true&lt;/code&gt; to your settings.json.&lt;/p&gt;

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

&lt;p&gt;Restart VSCode.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to move between Native Tabs
&lt;/h2&gt;

&lt;p&gt;Add shortcuts to &lt;code&gt;workbench.action.showPreviousWindowTab&lt;/code&gt; and &lt;code&gt;workbench.action.showNextWindowTab&lt;/code&gt; to move between them without having to navigate throughout the screen with the mouse cursor.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ctrl+shift+h"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workbench.action.showPreviousWindowTab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"when"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"!terminalFocus"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ctrl+shift+l"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workbench.action.showNextWindowTab"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"when"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"!terminalFocus"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;Also add a shortcut for creating a new Native Tab.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ctrl+shift+t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workbench.action.newWindowTab"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;Done. Enjoy your Native Tabs.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A year of ruby meetups in Kitchener</title>
      <dc:creator>lucasprag</dc:creator>
      <pubDate>Mon, 23 Dec 2019 04:43:53 +0000</pubDate>
      <link>https://forem.com/lucasprag/a-year-of-ruby-meetups-in-kitchener-5g72</link>
      <guid>https://forem.com/lucasprag/a-year-of-ruby-meetups-in-kitchener-5g72</guid>
      <description>&lt;p&gt;I've been living in Kitchener for over an year and in the first time I attended to the ruby workshop I created my &lt;a href="https://github.com/rails/rails/pull/34233" rel="noopener noreferrer"&gt;first PR&lt;/a&gt; to Rails 🎉&lt;/p&gt;

&lt;p&gt;It was quite simple of course, but in that workshop I've learned that it's not that hard to do open source. Eventually I found a small problem in Rails and I created &lt;a href="https://github.com/rails/rails/pull/36470" rel="noopener noreferrer"&gt;another PR&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then I started doing more open source in projects that I was using at work like &lt;a href="https://github.com/mezis/viscacha/pull/3" rel="noopener noreferrer"&gt;viscacha&lt;/a&gt;, &lt;a href="https://github.com/rails/sprockets/pull/599" rel="noopener noreferrer"&gt;sprockets&lt;/a&gt;, &lt;a href="https://github.com/itchyny/lightline.vim/pull/398" rel="noopener noreferrer"&gt;lightline.vim&lt;/a&gt;, tabulous PR &lt;a href="https://github.com/webdevel/tabulous/pull/2" rel="noopener noreferrer"&gt;#1&lt;/a&gt; and &lt;a href="https://github.com/webdevel/tabulous/pull/3" rel="noopener noreferrer"&gt;#2&lt;/a&gt;, &lt;a href="https://github.com/thadeu/vscode-run-rspec-file/pull/8" rel="noopener noreferrer"&gt;vscode-run-rspec-file&lt;/a&gt; and hopefully this list is only going to grow overtime.&lt;/p&gt;

&lt;p&gt;In other ruby workshops, it was really nice to be able to help other people's projects.&lt;/p&gt;

&lt;p&gt;The meetup when &lt;a href="https://github.com/jayelkaake" rel="noopener noreferrer"&gt;Jay El-Kaake&lt;/a&gt; gave a talk about &lt;a href="https://www.meetup.com/kw-ruby-on-rails/events/260999605/" rel="noopener noreferrer"&gt;how to make Rails faster than the speed of light&lt;/a&gt; was really interesting, I've learned a few things on how to do speed tests, how to reduce latency when connecting to your app/postsgresql/redis and much more!&lt;/p&gt;

&lt;p&gt;In the workshop focused on &lt;a href="https://www.meetup.com/kw-ruby-on-rails/events/265685895/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt; I helped a developer to participate and I decided to participate myself which was great. 🌟&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flucasprag.com%2Fassets%2Fimages%2Fposts%2Fhacktoberfest-email.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flucasprag.com%2Fassets%2Fimages%2Fposts%2Fhacktoberfest-email.png" alt="The email I got saying that I've completed the Hacktoberfest challenge."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I missed the talk about Rails and Docker, that was a shame, I wish I could have made for that one.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://www.meetup.com/kw-ruby-on-rails/events/259429067/" rel="noopener noreferrer"&gt;Career, Business and Software Development&lt;/a&gt; talk by &lt;a href="https://twitter.com/martinbasiri" rel="noopener noreferrer"&gt;Martin Basiri&lt;/a&gt; I've learned one thing or two about the business side of tech companies. He also talked about his first endeavor which was earphones that made it easier to untangle their cable - 4 seconds less than others - and how it failed when wireless earphones got popular.&lt;/p&gt;

&lt;p&gt;It was quite inspiring to see so many students and developers asking interesting questions in the &lt;a href="https://www.meetup.com/kw-ruby-on-rails/events/266616653/" rel="noopener noreferrer"&gt;Building a Career in Technology&lt;/a&gt; talk by &lt;a href="https://www.linkedin.com/in/robsciuk/" rel="noopener noreferrer"&gt;Rob Sciuk&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/ralphjanke/" rel="noopener noreferrer"&gt;Ralph Janke&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Not all meetups are very productive, but the last one of 2019 was really special and this is why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I talked to someone who was new to Ruby, did the classic blog tutorial&lt;/li&gt;
&lt;li&gt;I did open source by working on an &lt;a href="https://github.com/kwruby/kwruby.ca/issues/35" rel="noopener noreferrer"&gt;issue&lt;/a&gt; to automate the deployment of the &lt;a href="http://kwruby.ca/" rel="noopener noreferrer"&gt;KWRuby's website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;we talked about &lt;a href="https://elixir-lang.org/" rel="noopener noreferrer"&gt;Elixir&lt;/a&gt;, pattern matching and &lt;a href="https://twitter.com/dwhelan/" rel="noopener noreferrer"&gt;Declan&lt;/a&gt; gave us a lesson -- almost a talk by itself -- on aspects of the Erlang's OTP&lt;/li&gt;
&lt;li&gt;we talked about new things comming up to Ruby like pattern matching on ruby 2.7&lt;/li&gt;
&lt;li&gt;and there were lots of Pizza 🍕&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Definitely one of the best ruby workshops. So many things happened in just one meetup.&lt;/p&gt;

&lt;p&gt;Big thanks to &lt;a href="https://github.com/acant" rel="noopener noreferrer"&gt;Andrew&lt;/a&gt;, the person behind this group and all the people who have helped him.&lt;/p&gt;

&lt;p&gt;If you are in Kitchener/Waterloo I strongly recommend you to attend a few times to the &lt;a href="http://kwruby.ca/" rel="noopener noreferrer"&gt;KWRuby meetup&lt;/a&gt;. If not in the area, try to see if there are groups in your city. It's totally worthy.&lt;/p&gt;

&lt;center&gt;
&lt;h3&gt;2020 is going to be great! 💎&lt;/h3&gt;
&lt;/center&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to add columns with a default value to large tables</title>
      <dc:creator>lucasprag</dc:creator>
      <pubDate>Sun, 17 Nov 2019 01:13:08 +0000</pubDate>
      <link>https://forem.com/lucasprag/how-to-add-columns-with-default-to-large-tables-8mc</link>
      <guid>https://forem.com/lucasprag/how-to-add-columns-with-default-to-large-tables-8mc</guid>
      <description>&lt;p&gt;If you worked with a large database you know that you can't just run an &lt;code&gt;alter table&lt;/code&gt; to add a column with a default value, maybe you tried it and it failed -- like me awhile ago 🤕 --  but what if you really need to do that? That's what I'm about to tell you in these four simple steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Add the column with no default
&lt;/h3&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;AddCurrencyToAccounts&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;5.2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:accounts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:currency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&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 is going to run this SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"accounts"&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="nv"&gt;"currency"&lt;/span&gt; &lt;span class="nb"&gt;character&lt;/span&gt; &lt;span class="nb"&gt;varying&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. When creating new records for that table, set the desired default value using your code
&lt;/h3&gt;

&lt;p&gt;There are tons of ways of accomplishing it and it really depends on how you create your records, but this is good enough for the 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;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;currency&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="s2"&gt;"USD"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Backfill all your table rows with the desired default value
&lt;/h3&gt;

&lt;p&gt;If you have a large database you also probably already have a way of running code for all your records  asynchronously to finish it really fast -- If not let me know -- but if you don't have it, a &lt;code&gt;.find_each&lt;/code&gt; or a &lt;code&gt;.find_in_batches&lt;/code&gt; would probably do the trick:&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;Account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;currency: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;find_each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# .update_attributes doesn't touch updated_at&lt;/span&gt;
  &lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_attributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;currency: &lt;/span&gt;&lt;span class="s2"&gt;"USD"&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;Why not just run &lt;code&gt;Account.where(currency: nil).update_all(currency: "USD")&lt;/code&gt; ?&lt;/p&gt;

&lt;p&gt;Because this ☝️ is going to lock your table while your database updates all your rows, that's why we need to update individual records so the database locking only happens per row.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Finally, add the default value to your column 🎉
&lt;/h3&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;AddDefaultToCurrencyOnAccounts&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;5.2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;change_column&lt;/span&gt; &lt;span class="ss"&gt;:accounts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:currency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default: &lt;/span&gt;&lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;null: &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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is going to run this SQL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"accounts"&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="nv"&gt;"currency"&lt;/span&gt; &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="nb"&gt;character&lt;/span&gt; &lt;span class="nb"&gt;varying&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="nv"&gt;"currency"&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'USD'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="nv"&gt;"currency"&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that you can remove your code that sets the default value when creating your records from step #2 and it's done 🎉&lt;/p&gt;

</description>
      <category>rails</category>
      <category>database</category>
    </item>
    <item>
      <title>Little trick to use ctags to jump to definition even inside gems like Rails on vim</title>
      <dc:creator>lucasprag</dc:creator>
      <pubDate>Wed, 06 Nov 2019 01:40:52 +0000</pubDate>
      <link>https://forem.com/lucasprag/little-trick-to-use-ctags-to-jump-to-definition-even-inside-gems-like-rails-on-vim-244j</link>
      <guid>https://forem.com/lucasprag/little-trick-to-use-ctags-to-jump-to-definition-even-inside-gems-like-rails-on-vim-244j</guid>
      <description>&lt;p&gt;If you don't know what is ctags&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ctags is a programming tool that generates an index file of names found in source and header files of various programming languages. Depending on the language, functions, variables, class members, macros and so on may be indexed. -- Wikipedia&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the case of Ruby you can jump to a method definition, class, etc using  &lt;a href="http://ctags.sourceforge.net/"&gt;ctags&lt;/a&gt; which doesn't work 100% of the time but it helps a lot.&lt;/p&gt;

&lt;h1&gt;
  
  
  vim
&lt;/h1&gt;

&lt;p&gt;Vim has a native functionality where you can &lt;code&gt;:tag MyClass&lt;/code&gt; and it opens your class based on the index created by &lt;a href="http://ctags.sourceforge.net/"&gt;ctags&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can extend this functionality as much as you like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="c"&gt;" open tag of the word under the cursor, requires to run "ctargs -R ." before&lt;/span&gt;
command&lt;span class="p"&gt;!&lt;/span&gt; JumpToTag &lt;span class="nb"&gt;execute&lt;/span&gt; &lt;span class="s1"&gt;':tag '&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;cword&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

command&lt;span class="p"&gt;!&lt;/span&gt; JumpToTagOnVsplit &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;vsplit&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;execute&lt;/span&gt; &lt;span class="s1"&gt;':tag '&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;cword&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

command&lt;span class="p"&gt;!&lt;/span&gt; JumpToTagOnSplit &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;split&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;execute&lt;/span&gt; &lt;span class="s1"&gt;':tag '&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;cword&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;but there is one limitation when using Rails and other gems; you can't jump inside them, like &lt;code&gt;:tag ApplicationRecord&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  the trick
&lt;/h1&gt;

&lt;p&gt;You can run bundle install and set the path to install gems inside your project so when you run &lt;code&gt;ctags -R .&lt;/code&gt; all the gems get indexed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vendor/bundle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But remember to git ignore them&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/.gitignore_global
vendor/bundle

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  gutentags
&lt;/h1&gt;

&lt;p&gt;If you don't like run &lt;code&gt;ctags -R .&lt;/code&gt; all the time, there is a plugin for vim that runs ctags in the background while you are coding. It's called &lt;a href="https://github.com/ludovicchabant/vim-gutentags"&gt;vim-gutentags&lt;/a&gt;. All you need to do is install it.&lt;/p&gt;

&lt;p&gt;That's it, I hope you enjoyed this little trick to make our lives a bit easier when coding Rails on vim. 👍&lt;/p&gt;

</description>
      <category>vim</category>
      <category>rails</category>
      <category>neovim</category>
    </item>
    <item>
      <title>My editor journey: sublime, vim, emacs, vscode</title>
      <dc:creator>lucasprag</dc:creator>
      <pubDate>Sat, 04 Aug 2018 17:55:16 +0000</pubDate>
      <link>https://forem.com/lucasprag/my-editor-journey-sublime-vim-emacs-vscode-19k0</link>
      <guid>https://forem.com/lucasprag/my-editor-journey-sublime-vim-emacs-vscode-19k0</guid>
      <description>&lt;p&gt;I will talk about my experience using each of those text editors, maybe it could be useful for someone evaluating text editors to invest time learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  sublime text
&lt;/h2&gt;

&lt;p&gt;I started learning about programming when I was in high school, it was so much fun to write some code and see the results on the browser. I used sublime text because I was learning with blog posts and videos and most of the content mentioned sublime text. Also, it was fast and I had a few plugins installed to handle php, html, javascript and css. I used it for a few years at work too until the day I joined a company that had vim and emacs users.&lt;/p&gt;

&lt;h2&gt;
  
  
  vim
&lt;/h2&gt;

&lt;p&gt;The vim users worked on projects more closed to my own project so I started to check how they did things and then I started learning about vim. It was not cool, it was too hard to learn how to use it, to load new config files I had to restart vim every time and so much other problems, but since they did, I convinced myself that I could learn it too so I did.&lt;/p&gt;

&lt;p&gt;I used vim for a few months and what I like about vim the most is that it's optimized for editing files not creating new ones. For the most of the time, we're editing files and moving between lines of code so that makes sense. Finally I was happy and productive using vim.&lt;/p&gt;

&lt;h2&gt;
  
  
  neovim
&lt;/h2&gt;

&lt;p&gt;One day I heard about neovim, not sure exactly why I switched to it, but take a look on the github project for both projects:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmr475vfxouxinfcgxeaa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmr475vfxouxinfcgxeaa.png" alt="vim project with only one contributor" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Foogdvczt4j9mt5v49jxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Foogdvczt4j9mt5v49jxu.png" alt="vim project with 392 contributors" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait what? Only one contributor on the vim repository? How only one person could have done that? Checking the pull request list I saw that the author applies changes from other people as it was his changes. Ok, I didn't liked that, so I changed to neovim which gives credit for people when they contribute.&lt;/p&gt;

&lt;p&gt;UPDATE: I agree that my survey is too shallow. My see &lt;a href="https://dev.to/heast/comment/4gk4"&gt;this comment&lt;/a&gt;. But I still don't like that.&lt;/p&gt;

&lt;h2&gt;
  
  
  nvim + tmux
&lt;/h2&gt;

&lt;p&gt;At that time people was talking about &lt;code&gt;tmux&lt;/code&gt; which is a terminal multiplexer so you could split your terminal and have tabs and customize everything from shortcuts to how tmux looks like for example adding useful info to your status bar. I tried and I liked. Since I was using nvim in the terminal it worked very well and I even found some plugins to integrate them smoothly. Here is how it looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu4ncf7ir9rfeb0lx700j.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu4ncf7ir9rfeb0lx700j.gif" alt="using tmux and vim having different tabs and splits and running test in a split bellow" width="844" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don't use nvim anymore, but you can still find my configuration for &lt;a href="https://github.com/lucasprag/vimlociraptor" rel="noopener noreferrer"&gt;vim&lt;/a&gt; and &lt;a href="https://github.com/lucasprag/dotfiles/blob/master/tmux.conf" rel="noopener noreferrer"&gt;tmux&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I used this stack for 3 years and I was happy.&lt;/p&gt;

&lt;p&gt;Then I see myself managing configs and plugins for nvim, tmux, zsh to run well on terminator on my Debian at work and iTerm on macOS at home. Not everything worked well between plugins too, for example I had auto completation on nvim and it works well unless I'm using multiple cursors which is a feature from another plugin, the auto completation would work only for the first cursor because they didn't integrated with each other. I got other frustrating problems like that one and I see myself spending too much time debugging or trying alternative plugins, so I was tented to try something different and this is where emacs came to my attention.&lt;/p&gt;

&lt;h2&gt;
  
  
  emacs
&lt;/h2&gt;

&lt;p&gt;Emacs has a GUI app which makes me don't need terminator or iTerm anymore and it has his own shell written in elist called eshell, so I'd have one config and plugins for everything. I tried to start from scratch writing down every config as I did with vim, but it was too much to learn and I had to get some work done so I tried spacemacs and with some help I could be productive in no time.&lt;/p&gt;

&lt;p&gt;Spacemacs has vim key bindings so I was at home, I just needed to learn to handle different aspects of spacemacs like layouts and workspaces. It was easier to do things because it has a real-time display of available key bindings, so while you type you can see your options, also it is mnemonic so if you want layouts you'd use &lt;code&gt;SPC + l&lt;/code&gt;, if want to toggle something you'd use &lt;code&gt;SPC + t&lt;/code&gt;, if you want buffers you'd use &lt;code&gt;SPC + b&lt;/code&gt;, for projects &lt;code&gt;SPC + p&lt;/code&gt;, for files &lt;code&gt;SPC + f&lt;/code&gt; and to save a file you'd combine commands like &lt;code&gt;SPC + fs&lt;/code&gt; which means &lt;code&gt;spacemacs -&amp;gt; file -&amp;gt; save&lt;/code&gt; and &lt;code&gt;SPC + pt&lt;/code&gt; to see the project tree of files. Very straightforward right?&lt;/p&gt;

&lt;p&gt;It took me like a month to understand everything and to work well. I was not happy with everything, I got some bugs which is ok, I reported and I tried to fix them but I had to learn one more language (elisp) to be able to do that. It was a great experience because I was learning a lot of elisp which is a great language in my opinion so I was having fun, which made me use spacemacs for 6 months.&lt;/p&gt;

&lt;p&gt;Then I saw this video:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/8kCd4w4kc68"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Wait what? 10 years of love for Emacs undone by a week of VSCode? I have some friends who are happy with vscode too, they strongly recommend it. Ok, let's give it a try.&lt;/p&gt;

&lt;h2&gt;
  
  
  vscode
&lt;/h2&gt;

&lt;p&gt;I had to do some coding in a weekend so I switched to vscode and overall the experience was great, but I had to use the mouse a lot initially.&lt;/p&gt;

&lt;p&gt;I installed the vim key bindings which for my surprise also has support for common vim plugins like &lt;code&gt;vim-easymotion&lt;/code&gt;, &lt;code&gt;vim-surround&lt;/code&gt;, &lt;code&gt;vim-commentary&lt;/code&gt; and others that I've never heard of.&lt;/p&gt;

&lt;p&gt;Killer features for me that I found in vscode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cmd + p&lt;/code&gt; to open files using fuzzy search is faster and more intelligent (it puts recent files on top)&lt;/li&gt;
&lt;li&gt;shortcuts are more similar with browser shortcuts which makes my life easier as web developer&lt;/li&gt;
&lt;li&gt;config files are &lt;code&gt;JSON&lt;/code&gt; files and there is no need for too much customization (my config file has 22 lines and that's all)&lt;/li&gt;
&lt;li&gt;the integrated multiple terminal works really well and it has splits like tmux&lt;/li&gt;
&lt;li&gt;vscode is maintened by Microsoft which I think it's great to have a team working on it and adding features that integrate well with each other&lt;/li&gt;
&lt;li&gt;I don't need to debug vscode and I didn't find any bug so far&lt;/li&gt;
&lt;li&gt;I don't need to install too much plugins&lt;/li&gt;
&lt;li&gt;jump to definition for React&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vscode plugins I have installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=vscodevim.vim" rel="noopener noreferrer"&gt;Vim Keybindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=alefragnani.project-manager" rel="noopener noreferrer"&gt;Project Manager&lt;/a&gt; - easier to switch between projects using &lt;code&gt;ALT + CMD + p&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=alefragnani.Bookmarks" rel="noopener noreferrer"&gt;Bookmarks&lt;/a&gt; - &lt;code&gt;ALT + CMD + k&lt;/code&gt; to add a bookmark and &lt;code&gt;ALT + CMD + l&lt;/code&gt; to jump to the next bookmark&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=sleistner.vscode-fileutils" rel="noopener noreferrer"&gt;File Utils&lt;/a&gt; - easier to duplicate or rename files without using the mouse&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=rebornix.Ruby" rel="noopener noreferrer"&gt;Support for Ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=vayan.haml" rel="noopener noreferrer"&gt;Support for Ruby Haml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=castwide.solargraph" rel="noopener noreferrer"&gt;Autocompletation for Ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=misogi.ruby-rubocop" rel="noopener noreferrer"&gt;Linting for Ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-python.python" rel="noopener noreferrer"&gt;Support for Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=mjmcloug.vscode-elixir" rel="noopener noreferrer"&gt;Support for Elixir&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=dsznajder.es7-react-js-snippets" rel="noopener noreferrer"&gt;Support for React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=eserozvataf.one-dark-pro-monokai-darker" rel="noopener noreferrer"&gt;One Dark Pro Monokai Darker Theme&lt;/a&gt; - my favorite color schema&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fthtlo6h65n8hmfksan23.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fthtlo6h65n8hmfksan23.gif" alt="using vscode to switch to files, bookmark files and jump to bookmarks, and use the integrated terminal" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's my experience with text editors. Today I don't have to debug my editor to make simple things happen and I still can customize it for my needs. Yeah, I'm pretty happy with vscode and maybe you should try it too. I hope it was useful for someone.&lt;/p&gt;

&lt;p&gt;Also I'm looking forward to hear your opinion and experience about those text editors. Thanks.&lt;/p&gt;

</description>
      <category>vim</category>
      <category>emacs</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Use-case oriented rails applications</title>
      <dc:creator>lucasprag</dc:creator>
      <pubDate>Tue, 31 Jul 2018 14:54:27 +0000</pubDate>
      <link>https://forem.com/lucasprag/use-case-oriented-rails-applications-28jb</link>
      <guid>https://forem.com/lucasprag/use-case-oriented-rails-applications-28jb</guid>
      <description>&lt;p&gt;I will bring here an approachable solution for building rails applications using some fundamentals of the so-called clean architecture. But, what is it?&lt;/p&gt;

&lt;h1&gt;
  
  
  clean architecture
&lt;/h1&gt;

&lt;p&gt;It's hard to tell what it is without telling about the problem.&lt;/p&gt;

&lt;p&gt;The problem is, look at your rails application, try to identify what it does, open your &lt;code&gt;app&lt;/code&gt; folder and try to identify again.&lt;/p&gt;

&lt;p&gt;We can see some folders like controllers, models, helpers and so on. Even when opening one of those folders we cannot say what is does, but we can only say what that application have, like users or products. The clean architecture came to try to solve this problem.&lt;/p&gt;

&lt;p&gt;One thing we can notice on that rails applications is that it's screaming &lt;code&gt;web framework!&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But one thing we can never forget is that the &lt;strong&gt;web is a delivery system&lt;/strong&gt; and should not dominate our code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Faefxxs18lhzhhd12d3ci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Faefxxs18lhzhhd12d3ci.png" alt="the web is a delivery system" width="526" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  the proposal
&lt;/h1&gt;

&lt;p&gt;A picture is worth a thousand words so let's check some images from Robert C. Martin illustrating his proposal of what path the request should follow:&lt;/p&gt;

&lt;h3&gt;
  
  
  the user interacts with the system
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F17p8mdqnjjt88qqq96ys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F17p8mdqnjjt88qqq96ys.png" alt="the user interacts with the system" width="730" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  the delivery mechanism builds a request model and passes it to the boundary/interface
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmgwra7e3hesxylpx8cvs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmgwra7e3hesxylpx8cvs.png" alt="the delivery mechanism builds a request model and passes it to the boundary/interface" width="717" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  the interface knows which interactor to use and passes the request model to it
&lt;/h3&gt;

&lt;h3&gt;
  
  
  and the interactor executes the business rules
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fbj4vvazl2e89yi8rrag7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fbj4vvazl2e89yi8rrag7.png" alt="the interactor executes the business rules and interacts with entities" width="727" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  and interacts with entities
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fg5n8ynvx60x0jhs0p33g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fg5n8ynvx60x0jhs0p33g.png" alt="and interacts with entities" width="754" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  the interactor builds a result model and give it back to the boundary/interface
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fbtscyrgoskdpr5nuiawu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fbtscyrgoskdpr5nuiawu.png" alt="the interactor builds a result model and give it back to the boundary/interface" width="776" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  which will give it back to the delivery mechanism and the user
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fp3ot6qjf9cb9ruic3s1m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fp3ot6qjf9cb9ruic3s1m.png" alt="which will give it back to the delivery mechanism and the user" width="768" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the framework is just a detail in that architecture, it's a delivery mechanism. The interface to the user can be a website as well as a command line tool, the business rules go on the use cases which can interact with entities.&lt;/p&gt;

&lt;h1&gt;
  
  
  what about MVC?
&lt;/h1&gt;

&lt;p&gt;MVC (aka Model View Controller) is an architectural pattern which the user interacts with a controller who manipulates a model who updates the view where the user sees the result. I got this image from wikipedia to illustrate better:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu1q6tvb5x6tzr5p7t8l3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu1q6tvb5x6tzr5p7t8l3.png" alt="The MVC Process" width="478" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The MVC pattern was created by Trygve Reenskaug to use with SmallTalk for graphical user interface (GUI) software design in 1979.&lt;/p&gt;

&lt;p&gt;But what happens when we use this approach to build our entire web application?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd6kxz416rhzx0p1jrmmb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd6kxz416rhzx0p1jrmmb.png" alt="MVC as an web architecture is messy" width="570" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It gets messy.&lt;/p&gt;

&lt;p&gt;I'm not saying the MVC is bad, I'm saying that it's part of the delivery mechanism not of the application architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fy96c29rykvgrmc9chpvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fy96c29rykvgrmc9chpvu.png" alt="the delivery mechanism is the web framework, and the boundary/interface, interactor and entities are out application" width="761" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  real world use case
&lt;/h1&gt;

&lt;h2&gt;
  
  
  As an user, I want to pay an invoice
&lt;/h2&gt;

&lt;p&gt;Imagine you have a web application and you send invoices to your users, and then they pay their invoices. So that use case could be named 'pay_invoice' and to group related classes I will create a module call &lt;code&gt;Accoutant&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The goal is to call the use case in the controller like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoicesController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Accountant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay_invoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:invoice_id&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;credit_card_params&lt;/span&gt;&lt;span class="p"&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;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@invoice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;notice: &lt;/span&gt;&lt;span class="s1"&gt;'Invoice was successfully paid.'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&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;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@invoice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;error: &lt;/span&gt;&lt;span class="s1"&gt;'We got a problem paying that invoice'&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;In order to have that use case available we need to create a class like so:&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;require&lt;/span&gt; &lt;span class="s1"&gt;'caze'&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Accountant&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayInvoice&lt;/span&gt;
    &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Caze&lt;/span&gt;

    &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:invoice_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:credit_card&lt;/span&gt;

    &lt;span class="n"&gt;export&lt;/span&gt; &lt;span class="ss"&gt;:call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as: :pay_invoice&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;invoice_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credit_card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vi"&gt;@invoice_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;invoice_id&lt;/span&gt;
      &lt;span class="vi"&gt;@credit_card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;credit_card&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;call&lt;/span&gt;
      &lt;span class="c1"&gt;# register payment thought payment gateway (maybe background job)&lt;/span&gt;
      &lt;span class="c1"&gt;# change invoice status&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="kp"&gt;private&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;invoice&lt;/span&gt;
      &lt;span class="vi"&gt;@invoice&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;some points to notice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;there is only one public instance method (&lt;code&gt;call&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;this class has one responsibility&lt;/li&gt;
&lt;li&gt;easy to write specs&lt;/li&gt;
&lt;li&gt;I used the &lt;code&gt;caze&lt;/code&gt; gem to have a simple DSL to define use cases instead of doing this:
&lt;/li&gt;
&lt;/ul&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="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay_invoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credit_card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credit_card&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We add that use case to the &lt;code&gt;Accountant&lt;/code&gt; module like so:&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;require&lt;/span&gt; &lt;span class="s1"&gt;'caze'&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Accountant&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Caze&lt;/span&gt;

  &lt;span class="n"&gt;has_use_case&lt;/span&gt; &lt;span class="ss"&gt;:pay_invoice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;PayInvoice&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 we can say one thing that this application does which is pay invoices. Take a look on how the files are organized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F71ssjyd36uwnwqqwzbub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F71ssjyd36uwnwqqwzbub.png" alt="We have an use cases folder with an accountant.rb there and an accountant folder with the pay_invoice.rb there" width="239" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You don't really need to use the &lt;code&gt;caze&lt;/code&gt; gem, the important part of all this is:&lt;/p&gt;

&lt;h2&gt;
  
  
  We separated what the application &lt;strong&gt;HAS&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;models like invoice, account and so on that doesn't change very much (stable)&lt;/p&gt;

&lt;h2&gt;
  
  
  of what the application &lt;strong&gt;DOES&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;behaviors and use cases tend to change a lot while the business grows&lt;/p&gt;

&lt;h2&gt;
  
  
  when to write use cases?
&lt;/h2&gt;

&lt;p&gt;When you only need to manage resources, you can and should use the rails way which is resource oriented so it makes sense, but when you have a special logic and it's very unique to your business rules, you write use cases like the code above.&lt;/p&gt;

&lt;h1&gt;
  
  
  conclusion
&lt;/h1&gt;

&lt;p&gt;After all that work we can look on our application and quickly see what it does instead of just seeing resources which is what it has, you can also move between frameworks or create new interfaces to use your unique business rules.&lt;/p&gt;

&lt;p&gt;Keep in mind that there is no silver bullet in programming, but this is for sure a very effective approuch to keep your use cases organized and keep your software architecture clean.&lt;/p&gt;

&lt;h1&gt;
  
  
  references
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;Clean architecture by Robert Martin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=WpkDN78P884" rel="noopener noreferrer"&gt;Architecture the Lost Years by Robert Martin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/magnetis-backstage/clean-architecture-on-rails-e5e82e8cd326" rel="noopener noreferrer"&gt;Clean architecture on rails by Fabiano Beselga&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/magnetis/caze" rel="noopener noreferrer"&gt;caze gem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.gatherspace.com/static/use_case_example.html" rel="noopener noreferrer"&gt;use case examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/unclebobmartin/status/992073756150558720" rel="noopener noreferrer"&gt;"Nice" by Uncle Bob
&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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