<?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: Charlie Gardai</title>
    <description>The latest articles on DEV Community by Charlie Gardai (@moltenhead).</description>
    <link>https://dev.to/moltenhead</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%2F795285%2F066e83a8-00b8-452e-98d9-a26b37e0ad49.JPG</url>
      <title>DEV Community: Charlie Gardai</title>
      <link>https://dev.to/moltenhead</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/moltenhead"/>
    <language>en</language>
    <item>
      <title>Ruby : to __callee__ or not __callee__</title>
      <dc:creator>Charlie Gardai</dc:creator>
      <pubDate>Tue, 26 Sep 2023 15:07:44 +0000</pubDate>
      <link>https://dev.to/moltenhead/ruby-to-callee-or-not-callee-1gjl</link>
      <guid>https://dev.to/moltenhead/ruby-to-callee-or-not-callee-1gjl</guid>
      <description>&lt;p&gt;Ever met those instructions :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;__FILE__&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;__method__&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;__callee__&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;?&lt;/p&gt;

&lt;p&gt;I think we all met at least the first one while playing with Ruby within our early experimentations ... and maybe used the second one for debugging processes - if so I propose you to try a debugger like &lt;a href="https://github.com/pry/pry"&gt;pry&lt;/a&gt;, &lt;a href="https://github.com/deivid-rodriguez/byebug"&gt;byebug&lt;/a&gt;, &lt;a href="https://github.com/deivid-rodriguez/pry-byebug"&gt;pry-byebug&lt;/a&gt; you'll get lots of the information right away (if you are using Ruby &amp;gt;3.1 you even get an &lt;a href="https://dev.to/st0012/a-sneak-peek-of-ruby-s-new-debugger-5caa"&gt;integrated one&lt;/a&gt;).&lt;br&gt;
But do you know what does the last one ?&lt;/p&gt;
&lt;h2&gt;
  
  
  The difference with &lt;strong&gt;method&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First of all, let's identify what &lt;code&gt;__method__&lt;/code&gt; is doing :&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;world&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s2"&gt;"hello &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;__method__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;world&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executing this file will produce:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ &amp;gt; hello world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But why ?&lt;/p&gt;

&lt;p&gt;Simply put : &lt;code&gt;__method__&lt;/code&gt; is returning as a symbol the name of the method the instruction is in.&lt;br&gt;
Here the method is &lt;strong&gt;world&lt;/strong&gt;, so it &lt;strong&gt;puts&lt;/strong&gt; the interpolation of the string and the method symbol which gives : &lt;em&gt;hello world&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So what is the difference with &lt;code&gt;__callee__&lt;/code&gt; ?&lt;br&gt;
Well &lt;code&gt;__callee__&lt;/code&gt; is returning the actual name of the &lt;strong&gt;called method&lt;/strong&gt; dynamically as a symbol.&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's example ourselves
&lt;/h2&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;Foo&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;root_method&lt;/span&gt;
    &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s2"&gt;"you did &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;__method__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;root_callee&lt;/span&gt;
    &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s2"&gt;"you did &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;__calle__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&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="no"&gt;Foo&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="nf"&gt;tap&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;this&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root_method&lt;/span&gt;
  &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root_callee&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;File execution :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ &amp;gt; you did root_method
  &amp;gt; you did root_callee
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here nothing big differentiate both behaviours : both return their method name.&lt;/p&gt;

&lt;p&gt;Let's then put the &lt;code&gt;__callee__&lt;/code&gt; specificities 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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;
  &lt;span class="kp"&gt;alias_method&lt;/span&gt; &lt;span class="ss"&gt;:aliased_method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:root_method&lt;/span&gt;
  &lt;span class="kp"&gt;alias_method&lt;/span&gt; &lt;span class="ss"&gt;:aliased_callee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:root_callee&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Foo&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="nf"&gt;tap&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;this&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aliased_method&lt;/span&gt;
  &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aliased_callee&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;File execution :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ &amp;gt; you did root_method
  &amp;gt; you did aliased_callee
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what happened ?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The aliased method that uses &lt;code&gt;__method__&lt;/code&gt; interpolates the root method name.&lt;/li&gt;
&lt;li&gt;The aliased method that uses &lt;code&gt;__callee__&lt;/code&gt; interpolates with the aliased method name.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;__callee__&lt;/code&gt; instead of &lt;code&gt;__method__&lt;/code&gt; is looking up for the actual method name, not the one it originated from !&lt;/p&gt;

&lt;h2&gt;
  
  
  Ok ... but how can I use this ?
&lt;/h2&gt;

&lt;p&gt;That's a good question !&lt;/p&gt;

&lt;p&gt;Let's imagine a situation where we send automatic mailing to update an asynchronous task for our users .&lt;/p&gt;

&lt;p&gt;We will always send the same data structure, and the only thing that will change is the corpus of the mail.&lt;br&gt;
We could go the naive way and produce a &lt;code&gt;Mailer&lt;/code&gt; with every specific methods we need for every possible situations. But that's tedious and imply a lot of repetition - which we don't want !&lt;/p&gt;

&lt;p&gt;So how can we use &lt;code&gt;__callee__&lt;/code&gt; here to simplify our day to day life ?&lt;/p&gt;
&lt;h2&gt;
  
  
  A one Mailer to rule them all
&lt;/h2&gt;

&lt;p&gt;So we need a Mailer that will always send emails with 3 parameters : &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;user_name&lt;/code&gt;, a &lt;code&gt;job_id&lt;/code&gt;, to notify an asynchronous event to the users.&lt;br&gt;
The only things that will change depending on the event is :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the subject of the mail&lt;/li&gt;
&lt;li&gt;the corpus of the mail&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So first we need something that will be able to structure the needed data as we need it :&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;AsynchronUpdateMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionMailer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&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;default_mail_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;jid&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="vi"&gt;@email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;
    &lt;span class="vi"&gt;@name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt;
    &lt;span class="vi"&gt;@jid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jid&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="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="ss"&gt;subject: &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;__callee__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gsub&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="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;jid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:html&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;We now have an &lt;code&gt;AsynchronUpdateMailer&lt;/code&gt; that is able to receive parameters to structure a default email and uses &lt;code&gt;__callee__&lt;/code&gt; and the job id to structure the subject. That's Good !&lt;br&gt;
But we can't do anything with it yet.&lt;br&gt;
&lt;em&gt;We turn the method private because this should never get called : no need to send a default mail, what we need is a simple first structure to be able to quickly extend its behaviour with the less possible code&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So let's extend it a bit to turn it a little bit more usefull :&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;AsynchronUpdateMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionMailer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="no"&gt;VALID_ACTIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;%i[
    foo_success
    foo_failure
    bar_success
  ]&lt;/span&gt;

  &lt;span class="no"&gt;VALID_ACTIONS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;valid_alias&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="kp"&gt;alias_method&lt;/span&gt; &lt;span class="n"&gt;valid_alias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:default_mail_action&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What did we do here ?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We defined a constant that identify which actions this mailer is able to produce.&lt;/li&gt;
&lt;li&gt;when this Mailer is loaded by Rails, it will programmatically define an alias for every "valid action" that aliases &lt;code&gt;default_mail_action&lt;/code&gt;, and each of those aliases will be public&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ok ... that's good and all. But what about the corpus ? What is the interest of this proposition if everyone of the sent emails does the same ?&lt;br&gt;
Well, the answer is simple : we're going to use the amazing powers of Rails views system to resolve our situation !&lt;/p&gt;
&lt;h2&gt;
  
  
  Rails views to the rescue
&lt;/h2&gt;

&lt;p&gt;Every time a &lt;code&gt;ActionMailer::Base&lt;/code&gt; uses the &lt;code&gt;mail&lt;/code&gt; method it will rely on the called method name and the application file structure to obtain the view that matches :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the Mailer name to find the folder within the &lt;strong&gt;app/views&lt;/strong&gt; folder&lt;/li&gt;
&lt;li&gt;the given action name to find the corresponding &lt;strong&gt;.haml&lt;/strong&gt; file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So let's add our files where they need to be !&lt;br&gt;
Within the &lt;strong&gt;app/views&lt;/strong&gt; folder we create a folder that is te machine name of our Mailer : &lt;code&gt;app/views/asynchronous_update_mailer&lt;/code&gt;. We then create a &lt;code&gt;.haml&lt;/code&gt; for every action we need - corresponding to the aliases we defined :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;foo_success.haml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;foo_failure.haml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bar_success.haml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each one of them is a common haml file and icing on the cake : we event get access to the state of the Mailer within this haml file.&lt;br&gt;
So we can do things like :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haml"&gt;&lt;code&gt;&lt;span class="nt"&gt;%html&lt;/span&gt;
  &lt;span class="nt"&gt;%body&lt;/span&gt;
    &lt;span class="nt"&gt;%section&lt;/span&gt;
      &lt;span class="nt"&gt;%p&lt;/span&gt;
        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;
      &lt;span class="nt"&gt;%p&lt;/span&gt;
        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"You can use the number given within the subject of this mail to contact the support if need be !"&lt;/span&gt;
      ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So ? Can you feel the maintenability and scalability of this setup tickling your brain ?&lt;br&gt;
Obviously you can always go one step further, but here we potentially saved a lot of time and maintenance using the power of Rails !&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;__callee__&lt;/code&gt; is one of those tool Ruby proposes that we don't always need ... but can still be of great use in the right context.&lt;br&gt;
It always comes down to what we have and what we do with it. I'm sure you already made great use of it and can share with us in the comment some of your experiences with its usage !&lt;/p&gt;

&lt;h2&gt;
  
  
  That's it for today !
&lt;/h2&gt;

&lt;p&gt;Thank you for reading this article, and I hope it got you something interesting out of it. At least I had a blast typing it.&lt;/p&gt;

&lt;p&gt;I'm sure you already made great use of the &lt;code&gt;__callee__&lt;/code&gt; method, so don't hesitate to give your insights and personal examples in the comments : they will be greatly appreciated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enjoy your skills and have a great day !&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>programming</category>
    </item>
    <item>
      <title>Rails "around_action" : a less used callback</title>
      <dc:creator>Charlie Gardai</dc:creator>
      <pubDate>Fri, 22 Sep 2023 12:31:21 +0000</pubDate>
      <link>https://dev.to/moltenhead/rails-aroundaction-a-less-used-callback-10cf</link>
      <guid>https://dev.to/moltenhead/rails-aroundaction-a-less-used-callback-10cf</guid>
      <description>&lt;p&gt;The other day I was re-exploring Rails documentation to give me a good refresh on what I already knew and what I forgot or what I slept on. There are so much little things that can get out of your vision when you are under production constraints, that having a little step back from time to time can offer you marvels to the mind and skill.&lt;/p&gt;

&lt;p&gt;Lost in re-reading from the basics to the details, I fall back onto one of the core aspect of Rails : its callbacks. It's when I realized that there's a lot of them that I don't meet really often within the code bases I get the grasp on.&lt;br&gt;
One especially feels the shy one : &lt;strong&gt;around_action&lt;/strong&gt;, one of the &lt;a href="https://api.rubyonrails.org/classes/AbstractController/Callbacks.html"&gt;AbstractController::Callbacks&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Some terminology before we start
&lt;/h2&gt;

&lt;p&gt;Interpretation is an amazing spell the brain has ... but it comes with its defects. Let's ensure we speak the same language :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;action&lt;/strong&gt; is a controller method that gets called through a route of the application. &lt;em&gt;create, show, edit, update, index, destroy are the common RESTful conventions.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;What I will call a &lt;strong&gt;behavior&lt;/strong&gt; is anything that produces any kind of reading or interact with the application. It will most commonly be methods of any form.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Refreshing the basics
&lt;/h2&gt;

&lt;p&gt;You certainly know about &lt;strong&gt;before&lt;/strong&gt;, &lt;strong&gt;after&lt;/strong&gt; &lt;em&gt;actions&lt;/em&gt; - certainly the most commonly used callback types. Let's just have a small refresher to get us  :&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;NutmegsController&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="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:set_nutmeg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except: &lt;/span&gt;&lt;span class="sx"&gt;%i[create index]&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:grate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except: &lt;/span&gt;&lt;span class="sx"&gt;%i[create index destroy]&lt;/span&gt;
  &lt;span class="n"&gt;after_action&lt;/span&gt; &lt;span class="ss"&gt;:dispatch_gatherer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: :create&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;strong&gt;before_action&lt;/strong&gt; produces behaviors right before the action, in the order you pass them to the controller.&lt;br&gt;
&lt;em&gt;So when it can both &lt;strong&gt;set_nutmeg&lt;/strong&gt; and &lt;strong&gt;grate&lt;/strong&gt; it will first &lt;strong&gt;set_nutmeg&lt;/strong&gt; then &lt;strong&gt;grate&lt;/strong&gt; it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;after_action&lt;/strong&gt; produces behaviors right after the action if it is successful.&lt;br&gt;
&lt;em&gt;It's an adequate time to send the gatherer used to get the nutmeg to the central as an example.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Those are rather explicit about the moment they are executing the behaviors.&lt;/p&gt;
&lt;h2&gt;
  
  
  So what does &lt;strong&gt;around_action&lt;/strong&gt; ?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Yeah ... that's a good question.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If "before" and "after" are crystal clear about the process timeline, "around" can get a bit too exposed to appreciation.&lt;/p&gt;

&lt;p&gt;In short : &lt;strong&gt;around_action&lt;/strong&gt; is expecting to receive behaviors that will do something during the action. It will &lt;strong&gt;yield the action process&lt;/strong&gt; for the behavior. (&lt;a href="https://guides.rubyonrails.org/layouts_and_rendering.html#understanding-yield"&gt;a little yield refresher if need be&lt;/a&gt;)&lt;br&gt;
The previous sentence is essential to understand what we can actually do with &lt;strong&gt;around_action&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's continue with our nutmegs exploitation :&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;NutmegsController&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="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:set_nutmeg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except: &lt;/span&gt;&lt;span class="sx"&gt;%i[create index]&lt;/span&gt;
  &lt;span class="n"&gt;before_action&lt;/span&gt; &lt;span class="ss"&gt;:grate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except: &lt;/span&gt;&lt;span class="sx"&gt;%i[create index destroy]&lt;/span&gt;

  &lt;span class="n"&gt;around_action&lt;/span&gt; &lt;span class="ss"&gt;:dry_air&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;except: &lt;/span&gt;&lt;span class="sx"&gt;%i[create destroy]&lt;/span&gt;

  &lt;span class="n"&gt;after_action&lt;/span&gt; &lt;span class="ss"&gt;:dispatch_gatherer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: :create&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;dry_air&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;UndryableRoomException&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;get_air&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dry&lt;/span&gt;

    &lt;span class="k"&gt;yield&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;Here we want to make sure that the air is dry while we show or most of the time we interact with the nutmegs. It will first try to dry the air on any non filtered actions - &lt;em&gt;no need for it while we gather or destroy them&lt;/em&gt; - if it can't it will stop the action and alert the controller, elseway it will resume the action as expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rails gives a good example
&lt;/h2&gt;

&lt;p&gt;The Rails documentation is always a good start for anything and has a lot of very good examples about its usage. And it doesn't fall short on &lt;a href="https://guides.rubyonrails.org/action_controller_overview.html#after-filters-and-around-filters"&gt;this one&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;class&lt;/span&gt; &lt;span class="nc"&gt;ChangesController&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="n"&gt;around_action&lt;/span&gt; &lt;span class="ss"&gt;:wrap_in_transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: :show&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;wrap_in_transaction&lt;/span&gt;
      &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="k"&gt;begin&lt;/span&gt;
          &lt;span class="k"&gt;yield&lt;/span&gt;
        &lt;span class="k"&gt;ensure&lt;/span&gt;
          &lt;span class="k"&gt;raise&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;Rollback&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;Here what it does is something that could be a great usage of this callback : wrapping the action within a transaction to ensure any interaction with the database that will occur during its process. If all succeeds : it will resume the action as expected, if anything fails : we make sure that any change is rollback.&lt;/p&gt;

&lt;p&gt;This can become real handy if we need to ensure multiple interactions within this one action.&lt;br&gt;
&lt;em&gt;Take this case with a grain of salt though : it can underlie a potential code smell (cf : Single responsibility principle in SOLID). But sometimes it's the adequate solution.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Going modular
&lt;/h2&gt;

&lt;p&gt;To give you more insight about the mater and a more adequate way to scale your code :&lt;br&gt;
A potential way to reuse the bit of code Rails provide us and clear up the code in the same code : use a &lt;strong&gt;Concern&lt;/strong&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="c1"&gt;# app/controllers/concerns/transactionable.rb&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Transactionable&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Concern&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;wrap_in_transaction&lt;/span&gt;
    &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt;
      &lt;span class="k"&gt;ensure&lt;/span&gt;
        &lt;span class="k"&gt;raise&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;Rollback&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;It will give us the possibility to include the behavior within any controller we need - and potentially extend &lt;strong&gt;Transactionable&lt;/strong&gt; later :&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;# app/controllers/some_controller.rb&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SomeController&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="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Transactionable&lt;/span&gt;

  &lt;span class="n"&gt;around_action&lt;/span&gt; &lt;span class="ss"&gt;:wrap_in_transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="sx"&gt;%i[create update]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;around_action&lt;/strong&gt; may be a less used callback, but as for lots of things within Rails : it can sometimes resolve some of your niche problems with precision.&lt;/p&gt;

&lt;p&gt;And don't forget to dive back within the Rails documentation without intent from time to time when you feel so ... it's a great pleasure to re-enact your knowledge on some specific use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  That's it for today !
&lt;/h2&gt;

&lt;p&gt;Hope this little refresher gave you some food for thought. At least it was a pleasure typing it.&lt;/p&gt;

&lt;p&gt;Don't hesitate to give your insights and personal examples in the comments : they will be appreciated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enjoy your skills and have great day !&lt;/strong&gt;&lt;/p&gt;

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