<?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: Lucas Barret</title>
    <description>The latest articles on DEV Community by Lucas Barret (@yet_anotherdev).</description>
    <link>https://dev.to/yet_anotherdev</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%2F1027021%2Fd37a677a-87c0-49d7-9e43-0bd2e452fce3.jpg</url>
      <title>DEV Community: Lucas Barret</title>
      <link>https://dev.to/yet_anotherdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yet_anotherdev"/>
    <language>en</language>
    <item>
      <title>Action Text</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Tue, 28 Oct 2025 18:54:11 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/action-text-3g4o</link>
      <guid>https://dev.to/yet_anotherdev/action-text-3g4o</guid>
      <description>&lt;p&gt;Action Text is a ruby gem that is part of Rails. It enables you to write and display rich text in your app. &lt;/p&gt;

&lt;p&gt;But how does it work ? &lt;/p&gt;

&lt;h2&gt;
  
  
  Install Action Text
&lt;/h2&gt;

&lt;p&gt;First thing first let's set up our issue. You want to create a blog. &lt;br&gt;
Obviously in this blog you have articles.&lt;/p&gt;

&lt;p&gt;You create an article table and in this table you have a &lt;code&gt;content&lt;/code&gt; column. &lt;/p&gt;

&lt;p&gt;Eventually you decide that you would like to add rich text to these article content. &lt;/p&gt;

&lt;p&gt;You use Action Text, so let's install it :&lt;br&gt;
&lt;code&gt;bin/rails action_text:install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This generates a migration so you just need to run them. &lt;/p&gt;

&lt;p&gt;Eventually in your model &lt;code&gt;article.rb&lt;/code&gt; you just have to add &lt;code&gt;has_rich_text :content&lt;/code&gt; and Voilà !&lt;/p&gt;
&lt;h2&gt;
  
  
  How this table works
&lt;/h2&gt;

&lt;p&gt;This table is a polymorphic table where you store the name of the record and the id of the record. &lt;/p&gt;

&lt;p&gt;A row from this table look like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ActiveRecord::Base.connection.execute("select * from action_text_rich_texts")

{
  "id" =&amp;gt; 3,
  "body" =&amp;gt; "the body of your content",
  "created_at" =&amp;gt; "2025-10-26 10:39:22.112279",
  "name" =&amp;gt; "content",
  "record_id" =&amp;gt; 2,
  "record_type" =&amp;gt; "Article",
  "updated_at" =&amp;gt; "2025-10-26 17:17:09.672582"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when you update your article content like this : &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Article.find(2).update(content: 'new content')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It will not update the content of the article but the body of the related action_text_rich_text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Article.find(2).attributes

{
  "id" =&amp;gt; 2,
  "content" =&amp;gt; nil, # content is nil
  "created_at" =&amp;gt; 2025-10-26 10:39:22.106595000 UTC +00:00,
  "updated_at" =&amp;gt; 2025-10-26 17:17:09.674060000 UTC +00:00
}

ActiveRecord::Base.connection.execute("select * from action_text_rich_texts")

{
  "id" =&amp;gt; 3,
  "body" =&amp;gt; "new content",
  "created_at" =&amp;gt; "2025-10-26 10:39:22.112279",
  "name" =&amp;gt; "content",
  "record_id" =&amp;gt; 2,
  "record_type" =&amp;gt; "Article",
  "updated_at" =&amp;gt; "2025-10-26 17:17:09.672582"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How is this working ?
&lt;/h2&gt;

&lt;p&gt;This is done in fact through a simple trick : redefining the getter of the Article class. &lt;/p&gt;

&lt;p&gt;And this is done thought the &lt;code&gt;has_rich_text&lt;/code&gt; dsl that you use earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class_eval &amp;lt;&amp;lt;-CODE, __FILE__, __LINE__ + 1
  def #{name}=(body)
    self.#{name}.body = body
  end
CODE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And why it works ? Because create use new that use the getter to affect variable with the setter of the class.&lt;/p&gt;

&lt;p&gt;This also means that the bulk edit method, like &lt;code&gt;insert_all&lt;/code&gt; and &lt;code&gt;update_all&lt;/code&gt; does not work. &lt;/p&gt;

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

&lt;p&gt;That's it you know how rich text work and how the magic happens&lt;/p&gt;

</description>
      <category>rails</category>
    </item>
    <item>
      <title>Hot Reloading in Ruby</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Fri, 11 Jul 2025 04:56:07 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/hot-reloading-in-ruby-5gac</link>
      <guid>https://dev.to/yet_anotherdev/hot-reloading-in-ruby-5gac</guid>
      <description>&lt;p&gt;Developer eXperience or DX is really important. Something that we use every day and almost forget is Hot Reload; in Ruby World, there is a cool gem that is appreciated: Spring for Hot Server Reload. So, in this article, we will see how to build a simple preloader in Ruby.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polling
&lt;/h2&gt;

&lt;p&gt;There are several techniques to achieve what we want. But the easiest one stays polling. Basically, what we will do here is create a watcher that polls over the files of our current directory. Then, our app will reload the files if necessary.&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;Watcher&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;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vi"&gt;@relative_mtime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&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;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&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;watch&lt;/span&gt;
      &lt;span class="n"&gt;mtime_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"**/*"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&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;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@relative_mtime&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;mtime_max&lt;/span&gt;
        &lt;span class="vi"&gt;@relative_mtime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mtime_max&lt;/span&gt;
        &lt;span class="kp"&gt;true&lt;/span&gt;
      &lt;span class="k"&gt;else&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;h2&gt;
  
  
  App/Server Reloading
&lt;/h2&gt;

&lt;p&gt;Now we can build our app, this app is simple but it could be a Rails app. &lt;/p&gt;

&lt;p&gt;Here, you see that at the beginning, we &lt;code&gt;require&lt;/code&gt; the &lt;code&gt;Watcher&lt;/code&gt;, then a &lt;code&gt;test1&lt;/code&gt; file, and a &lt;code&gt;test2&lt;/code&gt; file. But with a little subtle thing. the first one is done with require and the other one with load. &lt;/p&gt;

&lt;p&gt;We are going to see why after.&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;'watcher.rb'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'test1'&lt;/span&gt;
&lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'test2.rb'&lt;/span&gt;

&lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"**/*"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;watcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Watcher&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;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="no"&gt;Kernel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="no"&gt;Test1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;
    &lt;span class="no"&gt;Test2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;
    &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;stale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;watcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stale&lt;/span&gt;
    &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"**/*"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&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;So now, if you change the &lt;code&gt;test2&lt;/code&gt; method, you will see the difference. But if you do so for &lt;code&gt;test1&lt;/code&gt;, it won't be reloaded. Using &lt;code&gt;require&lt;/code&gt; makes it impossible for you to reload this particular file.&lt;/p&gt;

&lt;p&gt;This will also work with autoload, but you must remove the constant first. &lt;/p&gt;

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

&lt;p&gt;Now you know how to make your own hot reload. And, of course, you can find the most effective way to do it. &lt;/p&gt;

&lt;p&gt;The Spring Gem has 2 strategies if I am not mistaken. First one the simplest is Polling, otherwise, it uses the &lt;code&gt;listen&lt;/code&gt; gem developed by Thibaut Guillaume Gentil.&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>Webhook backend in ruby</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Wed, 03 Jan 2024 06:42:19 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/webhook-backend-3bk5</link>
      <guid>https://dev.to/yet_anotherdev/webhook-backend-3bk5</guid>
      <description>&lt;p&gt;I have heard of Webhook for a while now. But I never used it, and I have struggled a bit to understand what was really happening. &lt;/p&gt;

&lt;p&gt;And as always, I think trying to implement the thing is one of the best ways to understand what is happening. So, after reading one book or two about Webhooks and API. I thought it was the time to implement a simple Webhook API.&lt;/p&gt;

&lt;p&gt;In this blog post, we will oversee all the non-functional and security parts. We will aim to understand how Webhooks are working and try to understand the spirit of it. But of course, these are important parts that need to be treated in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Webhook
&lt;/h2&gt;

&lt;p&gt;Webhook needs several things but let's try to put it simply. &lt;br&gt;
Of course we need two things : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Webhook API provider&lt;/li&gt;
&lt;li&gt;A Webhook API consumer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Webhook consumer needs to register with the provider and give a URL that can be requested when an event has happened. &lt;/p&gt;

&lt;p&gt;This URL is the callback URL, and it is an endpoint for the client to react to any change happening in the provider system. &lt;/p&gt;

&lt;p&gt;Then, we will need an Event history to be able to keep the client up to date on the event if any issue happens. &lt;/p&gt;

&lt;p&gt;Eventually, the Webhook consumer will need a callback endpoint to receive any updates. &lt;/p&gt;
&lt;h2&gt;
  
  
  Provider
&lt;/h2&gt;

&lt;p&gt;Let's say we have a job that launches the washing for our laundry machine. We want to provide a way to make the client aware of when the machine will be ended without polling. &lt;/p&gt;

&lt;p&gt;We will get back to this job later for now we only need to know that it is called &lt;code&gt;WashingJob&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, as we said, the API Consumer needs to register with the API provider. So, the provider needs a Webhook subscription endpoint. &lt;/p&gt;

&lt;p&gt;Let's have a look at the WebHook subscription model. &lt;br&gt;
This will take a receiver_url (that will be query when the job is over), the customer_id, and the event that has happened that triggers our webhook (here the end of the washing machine).&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;WebHookSubController&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;index&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;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;

    &lt;span class="no"&gt;WebHookSubscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;receiver_url: &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;:receiver_url&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="ss"&gt;topic: &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;:topic&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;customer_id: &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;:customer_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step for us is to have an event history in the API provider to know if the clients have received the event well.&lt;/p&gt;

&lt;p&gt;This will be needed in the case that API Consumer has not acknowledged the reception of the new event. So they can get the history and update every event that has not been received on their side. This can happen in different cases. Downtime of the API Receiver endpoint or server for 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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateEventHistory&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;7.1&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;create_table&lt;/span&gt; &lt;span class="ss"&gt;:event_histories&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;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:topic&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:delivery_status&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:customer_id&lt;/span&gt;

      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timestamps&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;Now we can take a look to the washing job. This will be pretty simple. &lt;/p&gt;

&lt;p&gt;So, as you see below, we retrieved the customer subscription to this event. Then we create a row in our history so the customers can have a trace of the event, and, as we said before, be sure to be up to date on the history if there is any issue.&lt;/p&gt;

&lt;p&gt;Then, we query the endpoint of the customer that is associated with this webhook subscription. If it is successful we update our event history to 'delivered' if not successful it is updated to 'not_delivered'.&lt;/p&gt;

&lt;p&gt;What is important after that is to create an endpoint for the customer to query the event history. But we won't tackle that here.&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;'uri'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'net/http'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WashingJob&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationJob&lt;/span&gt;
  &lt;span class="n"&gt;queue_as&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="nb"&gt;sub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;WebHookSub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;topic: &lt;/span&gt;&lt;span class="s1"&gt;'washing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;customer_id: &lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;ev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;EventHistory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create!&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;topic: &lt;/span&gt;&lt;span class="s1"&gt;'washing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;customer_id: &lt;/span&gt;&lt;span class="nb"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;delivery_status: &lt;/span&gt;&lt;span class="s1"&gt;'delivering'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;created_at&lt;/span&gt;
      &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTPSuccess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="no"&gt;EventHistory&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;customer_id: &lt;/span&gt;&lt;span class="nb"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;topic: &lt;/span&gt;&lt;span class="s1"&gt;'washing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;delivery_status: &lt;/span&gt;&lt;span class="s1"&gt;'delivering'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created_at&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;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;delivery_status: &lt;/span&gt;&lt;span class="s1"&gt;'delivered'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="no"&gt;EventHistory&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;customer_id: &lt;/span&gt;&lt;span class="nb"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;topic: &lt;/span&gt;&lt;span class="s1"&gt;'washing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;delivery_status: &lt;/span&gt;&lt;span class="s1"&gt;'delivering'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created_at&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;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;delivery_status: &lt;/span&gt;&lt;span class="s1"&gt;'not_delivered'&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;
  
  
  Receiver
&lt;/h2&gt;

&lt;p&gt;So, the customer who wants to know if the washing job is over must give an endpoint. We need another server, though, that has an endpoint.&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;WebhookEndpointController&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;index&lt;/span&gt; 
    &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:plain&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Event Accepted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:status&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;202&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 this endpoint, we responded to the API provider that we received the event with no problem. We need to do that because the API provider keeps the Event History, as we discussed earlier. If we do not respond when we want to check the event history, we will see an inconsistent state, and this could be harmful to us.&lt;/p&gt;

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

&lt;p&gt;In this blog post, we have seen how to basically implement Webhook in Ruby. We have overlooked a lot of aspects of it. But we know that this needs work both from the API Provider side and the API Consumer side. &lt;/p&gt;

&lt;p&gt;Moreover, we need several endpoints to make Webhooks work. And give a great developer experience to API consumers.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Testing GraphQL with Ruby</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Fri, 08 Dec 2023 02:00:58 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/testing-graphql-with-ruby-5g5h</link>
      <guid>https://dev.to/yet_anotherdev/testing-graphql-with-ruby-5g5h</guid>
      <description>&lt;p&gt;This will be a rapid and simple article about how to test your GraphQL code in a Rails app with RSpec.&lt;/p&gt;

&lt;p&gt;When it comes to Rails and GraphQL, one question that you could ask yourself is. How can I test my queries or mutations?&lt;/p&gt;

&lt;p&gt;Should I send an HTTP request? It seems not necessary to do that; what you want is to test the logic of my GraphQL queries or mutations.&lt;/p&gt;

&lt;p&gt;Do not worry. You don't have to.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to test
&lt;/h2&gt;

&lt;p&gt;Let's say you have a simple Schema with a Type called TestableType and a query that resolves testable, which has only a field called &lt;code&gt;tested.&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;TheSchema&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;GraphQL&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;

  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestableType&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;GraphQL&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Object&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:tested&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;String&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;Query&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;GraphQL&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Object&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:testable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;TestableType&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;true&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;testable&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"You can test me"&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="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Query&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;To use graphql, you do not need any framework. You can define everything in the same file.&lt;/p&gt;

&lt;p&gt;Now, for testing, we need to use the execute method of the schema. And the string of graphql query that I want to execute. &lt;/p&gt;

&lt;p&gt;With what we did earlier, it would look like this if we use minitest.&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;TestMeme&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Minitest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Test&lt;/span&gt; 
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;
    &lt;span class="vi"&gt;@query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;GQL&lt;/span&gt;&lt;span class="sh"&gt;
      {
        testable {
          name
        }
      }
&lt;/span&gt;&lt;span class="no"&gt;    GQL&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;test_that_kitty_can_eat&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="no"&gt;TamereSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@query&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'data'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'testable'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"Pogo Stick"&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now you know how to test your graphql queries without making HTTP requests. &lt;/p&gt;

&lt;p&gt;I hope this post helped you to understand more about Ruby and GraphQL. When I began to use GraphQL with Ruby, this was one of the first questions I asked myself. &lt;/p&gt;

&lt;p&gt;Here is a gist if you want to see it in action in a Ruby file: &lt;a href="https://gist.github.com/Lucas-Barret/b3db09d231165703e5f31ba52487ec60"&gt;https://gist.github.com/Lucas-Barret/b3db09d231165703e5f31ba52487ec60&lt;/a&gt; &lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>graphql</category>
    </item>
    <item>
      <title>Make your own HTTP server in ruby</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Wed, 22 Nov 2023 18:45:16 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/make-your-own-http-server-in-ruby-38em</link>
      <guid>https://dev.to/yet_anotherdev/make-your-own-http-server-in-ruby-38em</guid>
      <description>&lt;p&gt;Foundational stuff is too much overlooked in our Software Engineering.  I mean, I know few people who want to dive into protocols and how servers work. Whereas I think these are key and thrilling understandings of how things work. &lt;/p&gt;

&lt;p&gt;In this article, we will dive into how to build our own HTTP server with Ruby. &lt;/p&gt;

&lt;h2&gt;
  
  
  HTTP
&lt;/h2&gt;

&lt;p&gt;We are not going to dive deep into each corner of the protocol. But at least having the definition is important: HTTP is a stateless protocol of the Application layer based on TCP.&lt;/p&gt;

&lt;p&gt;In this article, we will focus on HTTP 1.1.&lt;/p&gt;

&lt;h2&gt;
  
  
  From TCP server
&lt;/h2&gt;

&lt;p&gt;So this is dumb, but what is the role of a server? Get the request from the clients and give them an appropriate response. HTTP messages follow a structure. The request has the verb and the path they want to access and, finally, the protocol version.&lt;/p&gt;

&lt;p&gt;So first thing, our server will need to accept the connection as we said before, HTTP is based upon TCP. So we will need to open a TCP socket on our machine. &lt;/p&gt;

&lt;p&gt;In Ruby, nothing is that simple we can use the socket library. And since Ruby loves OOP we will wrap everything in a class.&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;# http_server.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'socket'&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HttpServer&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;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TCPServer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="n"&gt;port&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;Then we will need to accept the connection as we said and keep the connection open to any client in our HttpServer class let's define an accept_connection method.&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;accept_connection&lt;/span&gt; 
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&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;
  
  
  To HTTP Server
&lt;/h2&gt;

&lt;p&gt;Now that we accept connection over TCP, we can analyze the message we receive. First, we can see that the message we receive is an HTTP request.&lt;/p&gt;

&lt;p&gt;And this is much simpler than we think. The sockets are Streams of data you can write and read from them as data come.&lt;/p&gt;

&lt;p&gt;So we are going to read from our stream with the gets function. &lt;/p&gt;

&lt;p&gt;Then we will need to do something really important in all HTTP servers: parsing the HTTP request to know what to answer to know how to respond to the client.&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;accept_connection&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;
    &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt;
    &lt;span class="n"&gt;verb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;protocol&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'HTTP/1.1'&lt;/span&gt;
      &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="n"&gt;response_hello_world&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; 
      &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;'Connection Refuse'&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;For the response, we can define something 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;def&lt;/span&gt; &lt;span class="nf"&gt;response_hello_world&lt;/span&gt;
 &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;HTTPRESPONSE&lt;/span&gt;&lt;span class="sh"&gt;
  HTTP/1.1 200
  Content-Type: text/html

  Hello World
&lt;/span&gt;&lt;span class="no"&gt;  HTTPRESPONSE&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's build an HTTP client to see how our server behaves. &lt;/p&gt;

&lt;h2&gt;
  
  
  HTTP Client
&lt;/h2&gt;

&lt;p&gt;As you can imagine, we will need a TCP socket again. We must connect to the already opened TCP socket for our Web server and then send an HTTP request.&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;# tcp_client.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'socket'&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TCPSocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5678&lt;/span&gt;
&lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;HTTPMSQ&lt;/span&gt;&lt;span class="sh"&gt;
GET /test HTTP/1.1
&lt;/span&gt;&lt;span class="no"&gt;HTTPMSQ&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we put a correct HTTP request with the method, the header and the protocol. But if we did not, as we have seen before, we would end up with a &lt;code&gt;Connection refuse&lt;/code&gt; as defined in &lt;code&gt;accept_connection&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Routing and Controllers
&lt;/h2&gt;

&lt;p&gt;So what we did was pretty simple, and we added only one path and case. Now what would happen if we want to take a different path?&lt;/p&gt;

&lt;p&gt;We can define a route class that will take care of reading the path and routing to the correct resources.&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;Router&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;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&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;route&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'/test'&lt;/span&gt;
      &lt;span class="s2"&gt;"hello tester"&lt;/span&gt;
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'/world'&lt;/span&gt;
      &lt;span class="s2"&gt;"hello world"&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;Then we can define a builder for the HTTP response :&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;HttpResponse&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;build&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="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;HTTPRESPONSE&lt;/span&gt;&lt;span class="sh"&gt;
HTTP/1.1 200
Content-Type: text/html

&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;
&lt;/span&gt;&lt;span class="no"&gt;    HTTPRESPONSE&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;Let's change a bit our &lt;code&gt;accept_connection&lt;/code&gt; method :&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;accept_connection&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;
      &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gets&lt;/span&gt;

      &lt;span class="n"&gt;verb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;protocol&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"HTTP/1.1"&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Router&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;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;
        &lt;span class="n"&gt;http_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&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="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="n"&gt;http_response&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;'Connection Refuse'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&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;But We could even do something more complicate, as within Rails with ActiveController and ActionPack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Even Further
&lt;/h2&gt;

&lt;p&gt;This is a bit of, but we could even do something more complicated with CRUD routes and controllers. This is inspired by this article: &lt;a href="https://tommaso.pavese.me/2016/07/26/a-rack-application-from-scratch-part-2-routes-and-controllers/"&gt;https://tommaso.pavese.me/2016/07/26/a-rack-application-from-scratch-part-2-routes-and-controllers/&lt;/a&gt; and how ActionPack and ActionController works inside Rails.&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;TestController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
    &lt;span class="s2"&gt;"Hello Test"&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;class&lt;/span&gt; &lt;span class="nc"&gt;Router&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;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&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;camelize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^[a-z\d]*/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capitalize!&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;string&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="sr"&gt;/(_)([a-z\d]*)/i&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;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$2&lt;/span&gt;
      &lt;span class="n"&gt;substituted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capitalize!&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;
      &lt;span class="n"&gt;substituted&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;string&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;constantize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;camel_cased_word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;const_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;camel_cased_word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;route&lt;/span&gt;
    &lt;span class="n"&gt;controller_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;camelize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@path&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"Controller"&lt;/span&gt;
    &lt;span class="n"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;constantize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;controller_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;controller&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'index'&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;It's pretty cool to stroll in the foundational stuff of the Web and understand in a concrete way what is going on. There is so much more to understand only with. Just the Headers or Cookies, for example. &lt;/p&gt;

&lt;p&gt;But at least now we know how a Web Server can serve the response from our web application. Of course, this is a simplistic version, and it lacks many things. &lt;/p&gt;

&lt;p&gt;We also did not use Rack to interface our web application and web servers. But I wanted to keep it as straightforward as possible to understand the bare bones of Web servers.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Ruby Dive in the C: Make a Ruby-Pg lite extension</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Mon, 06 Nov 2023 06:14:14 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/ruby-dive-in-the-c-make-a-ruby-pg-lite-extension-4122</link>
      <guid>https://dev.to/yet_anotherdev/ruby-dive-in-the-c-make-a-ruby-pg-lite-extension-4122</guid>
      <description>&lt;p&gt;In this article, I wanted to do two things. First, understand how the ruby-pg gem works and then how to create a C extension.&lt;/p&gt;

&lt;p&gt;We will walk through both in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the C extension
&lt;/h2&gt;

&lt;p&gt;There is several blog post on how to create a C extension, for example, &lt;a href="https://www.rubyguides.com/2018/03/write-ruby-c-extension/"&gt;https://www.rubyguides.com/2018/03/write-ruby-c-extension/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But Basically, you have to create an &lt;code&gt;extconf.rb&lt;/code&gt; file 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="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'mkmf'&lt;/span&gt;

&lt;span class="n"&gt;create_header&lt;/span&gt;
&lt;span class="n"&gt;create_makefile&lt;/span&gt; &lt;span class="s1"&gt;'pgext'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run it with ruby : &lt;code&gt;ruby extconf.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This will create a makefile, and then you can create a C file called exactly pgext.c because the Makefile has been created for it.&lt;/p&gt;

&lt;p&gt;Do not forget to make your libpq library available for your libraries for example in your Makefile. In your &lt;code&gt;CPPFLAGS&lt;/code&gt; add &lt;code&gt;-I/opt/homebrew/opt/libpq/include&lt;/code&gt; and in your &lt;code&gt;dldflags&lt;/code&gt; add &lt;code&gt;-L/opt/homebrew/opt/libpq/lib&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  LibPQ
&lt;/h2&gt;

&lt;p&gt;LibPQ is the C library that abstracts everything and enables it to connect to a Postgres database. There is a lot of function and data structure in this lib. &lt;/p&gt;

&lt;p&gt;But we will focus on the main one to be able to connect and execute a query. And eventually, print the result of our query. &lt;/p&gt;

&lt;h2&gt;
  
  
  Connect to Postgres
&lt;/h2&gt;

&lt;p&gt;First, we must create a data structure that will encapsulate our C connection for the Ruby World.&lt;/p&gt;

&lt;p&gt;For that, we need to wrap the PGConn data structure of LibPQ and then create a pg_connection_type that will hold this PGConn and make the connection accessible in the Ruby World.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;PGconn&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pgconn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;t_pg_connection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;rb_data_type_t&lt;/span&gt; &lt;span class="n"&gt;pg_connection_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wrap_struct_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"MyPG::Conn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dmark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dfree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RUBY_DEFAULT_FREE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dsize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn_size&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="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RUBY_TYPED_FREE_IMMEDIATELY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can define a &lt;code&gt;pg_conn&lt;/code&gt; function to get the connection info as an argument. This function will return a VALUE pointer to &lt;code&gt;MyPG::Conn&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;To get a VALUE pointer, we use the &lt;code&gt;TypedData_Make_Struct&lt;/code&gt; function. This function will allocate the memory necessary to hold our connection and link the t_pg_connection to the pg_connection_type. Eventually, it will give you back the VALUE pointer to your data structure, which is accessible in the Ruby world.&lt;/p&gt;

&lt;p&gt;After that, we only have to use the &lt;code&gt;PQconnectdb&lt;/code&gt; function with the connection information, and our connection will be established.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt;
&lt;span class="nf"&gt;pg_conn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;t_pg_connection&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="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;conninfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TypedData_Make_Struct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                     &lt;span class="n"&gt;t_pg_connection&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;pg_connection_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;pgconn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PQconnectdb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conninfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&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;That's cool, but having a connection without being able to execute queries is not very useful, right? &lt;/p&gt;

&lt;h2&gt;
  
  
  Executing Queries
&lt;/h2&gt;

&lt;p&gt;As before, we must define our data structure and everything accessible in the Ruby World. We also need to declare a VALUE pointer, but that's a bit of a foreshadowing; let's discuss that later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;my_rb_pg_result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="n"&gt;PGresult&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pgresult&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;t_pg_result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;rb_data_type_t&lt;/span&gt; &lt;span class="n"&gt;pg_result_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wrap_struct_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"MyPG::Result"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dmark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dfree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RUBY_DEFAULT_FREE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dsize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;res_size&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="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RUBY_TYPED_FREE_IMMEDIATELY&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;So before executing your query, you have to get the connection to the database you made earlier. Thanks to this function: &lt;code&gt;TypedData_Get_Struct&lt;/code&gt;, the klass is still &lt;code&gt;MyPG::Conn&lt;/code&gt;, so we can pass klass to the connection data.&lt;/p&gt;

&lt;p&gt;Then, we have to allocate memory for the result of the query. We use the same function as before, but now, we can't use &lt;code&gt;klass&lt;/code&gt; as the first argument since this is not the type of Ruby Object. &lt;/p&gt;

&lt;p&gt;We have to pass: &lt;code&gt;my_rb_pg_result&lt;/code&gt;. Indeed, you need the type to match your class, and my_rb_pg_result will represent &lt;code&gt;MyPG::Result&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;After that, execute the query upon the current connection. The query will be the first argument of the function that we define. We need to parse it as a string C string object before to use it.&lt;/p&gt;

&lt;p&gt;Then you can execute your query with &lt;code&gt;PQexec&lt;/code&gt; of LibPQ with the current connection and store it in the PGResult data structure which is encapsulate in our own C structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt;
&lt;span class="nf"&gt;pg_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;t_pg_connection&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="n"&gt;t_pg_result&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;TypedData_Get_Struct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                       &lt;span class="n"&gt;t_pg_connection&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;pg_connection_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StringValueCStr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;rb_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TypedData_Make_Struct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_rb_pg_result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                     &lt;span class="n"&gt;t_pg_result&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;pg_result_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;pgresult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PQexec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;pgconn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rb_result&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;h3&gt;
  
  
  Fun fact: reading the code of Ruby language, I think I have discovered why this is called klass and not klass and even in the Ruby language. The reason is that there is already a reserved keyword &lt;code&gt;class&lt;/code&gt; in C; that's it.
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Printing value
&lt;/h2&gt;

&lt;p&gt;Once you have executed your query, you would like at least to see the result. &lt;/p&gt;

&lt;p&gt;To do that, you can get the value in the field of the result with PQgetValue, given the result of the query and the position in the result matrix.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; 
&lt;span class="nf"&gt;pg_printvalue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;t_pg_result&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;TypedData_Get_Struct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;klass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                       &lt;span class="n"&gt;t_pg_result&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;pg_result_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                       &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%-15s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PQgetvalue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;pgresult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;j&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;h2&gt;
  
  
  Using the extension
&lt;/h2&gt;

&lt;p&gt;If you want to use your extension to do that, you must create an &lt;code&gt;Init_pgext&lt;/code&gt; function, which will define every constants and make them available in the Ruby World.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Init_pgext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;c_myPG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rb_define_module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyPG"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="n"&gt;my_rb_pg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rb_define_class_under&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c_myPG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                         &lt;span class="s"&gt;"Conn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                         &lt;span class="n"&gt;rb_cObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;my_rb_pg_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rb_define_class_under&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c_myPG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                          &lt;span class="s"&gt;"Result"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                          &lt;span class="n"&gt;rb_cObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;rb_define_singleton_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_rb_pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"conn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;pg_conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;rb_define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_rb_pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"exec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;pg_exec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;rb_define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_rb_pg_result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"printvalue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;pg_printvalue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can compile your extension and eventually use it in your Ruby Code like the following:&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_relative&lt;/span&gt; &lt;span class="s1"&gt;'./pgext'&lt;/span&gt;

&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MyPG&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"dbname = postgres"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;SQL&lt;/span&gt;&lt;span class="sh"&gt;
SELECT * FROM pg_catalog.pg_tables WHERE schemaname 
!= 'pg_catalog' AND schemaname != 'information_schema';
&lt;/span&gt;&lt;span class="no"&gt;SQL&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;printvalue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#-&amp;gt; table_name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;So in this article, we've managed to both: create a C extension and an essential way to connect and execute queries in Postgres. &lt;/p&gt;

&lt;p&gt;We have created both a C extension and connect, and execute arbitrary queries in our Postgres instance without any extra gem.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>postgres</category>
      <category>database</category>
    </item>
    <item>
      <title>Pessimistic Locking ( Rails Internal )</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Sun, 22 Oct 2023 12:39:15 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/pessimistic-locking-rails-internal--b67</link>
      <guid>https://dev.to/yet_anotherdev/pessimistic-locking-rails-internal--b67</guid>
      <description>&lt;p&gt;Recently, I had the opportunity to interview Ben Sheldon, the creator and maintainer of GoodJob. You can listen at it here : &lt;a href="https://share.transistor.fm/s/6bc570cc"&gt;https://share.transistor.fm/s/6bc570cc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I want to create an article to understand more about the gem we discover or rediscover in GemRubyShow. &lt;/p&gt;

&lt;p&gt;GoodJob is ActiveJob Backend for your background Job. It works only with Rails and is backed by Postgres. It uses this interesting Pub/Sub mechanism of Postgres called &lt;code&gt;LISTEN NOTIFY.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you want to learn more about GoodJob, you can listen to the podcast. It was an excellent discussion with Ben Sheldon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Locks in Rails
&lt;/h2&gt;

&lt;p&gt;According to Postgres documentation: Advisory Locks are locks that have application-defined meanings. This is called Advisory Locks because it is up to you (and your app) to use them correctly. Advisory Locks avoid table bloat and are automatically cleaned up by the server at the end of the session.&lt;/p&gt;

&lt;p&gt;There are two locking options in Rails : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimistic Locking (activerecord/lib/active_record/locking/optimistic.rb)&lt;/li&gt;
&lt;li&gt;Pessimistic Locking (activerecord/lib/active_record/locking/pessimistic.rb)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's go with Pessimistic Lock for this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pessimistic Lock
&lt;/h2&gt;

&lt;p&gt;In Rails, pessimistic Lock is based upon row-level locking of SQL. It might be worth it to understand Row Level locking.&lt;/p&gt;

&lt;p&gt;We have several levels of row locking from stronger to weaker: FOR UPDATE, FOR NO KEY UPDATE, FOR SHARE,  FOR KEY SHARE.&lt;/p&gt;

&lt;p&gt;We will only look for the FOR UPDATE keyword since it is the most used today and the default behavior in Rails.&lt;/p&gt;

&lt;p&gt;But you can learn more about row-level locking in Postgres documentation. There is also this excellent &lt;a href="https://postgrespro.com/blog/pgsql/5968005"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FOR UPDATE
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;FOR UPDATE,&lt;/code&gt; the more robust row-level locking, You will have different behavior depending on your transaction isolation level. &lt;/p&gt;

&lt;p&gt;If you are in READ COMMITTED, you will wait for the transaction to finish before getting the lock and be able to do the SELECT FOR UPDATE.&lt;/p&gt;

&lt;p&gt;Nevertheless, if you have a higher level of Isolation READ REPEATABLE or SERIALIZABLE, you could have an &lt;code&gt;ActiveRecord::SerializationFailure&lt;/code&gt; raised. &lt;/p&gt;

&lt;p&gt;For example, in the following case : &lt;/p&gt;

&lt;p&gt;Let's say you launch a transaction where you lock the first company, update the company's name, and do a bunch of stuff materialized by the sleep 10.&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;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="n"&gt;p1&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;lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'FOR SHARE'&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;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Hey'&lt;/span&gt;
  &lt;span class="nb"&gt;sleep&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
  &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save!&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 meanwhile, you (or your colleague) trigger this transaction&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;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="n"&gt;c1&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;first&lt;/span&gt;
  &lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Basecamp'&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s2"&gt;"Updating first company name to &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save!&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s1"&gt;'new name'&lt;/span&gt;
&lt;span class="nb"&gt;p&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;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your terminals, you will see that the first transaction is processing while the second will wait for the row to be unlocked&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;##Waiting for the first transaction to be end
Updating first company name to Hey
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  REPEATABLE READ
&lt;/h3&gt;

&lt;p&gt;Then, in another session and transaction, you try to get the first company, lock it, and update the name. &lt;/p&gt;

&lt;p&gt;The difference is that you increase the transaction level with &lt;code&gt;REPEATABLE READ&lt;/code&gt;, for 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;p1&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;first&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="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;isolation: :repeatable_read&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;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lock!&lt;/span&gt;
  &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Hey'&lt;/span&gt;
  &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save!&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 this context, the error is raised when you try to acquire a lock on a row that has been modified since you have read it for the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rails stack trace
&lt;/h2&gt;

&lt;p&gt;Rails implementation is simple because all the complexity is old by Postgres for the Row level locking.&lt;/p&gt;

&lt;p&gt;Nonetheless, I find it interesting to dig into the Rails code and understand this framework more.&lt;/p&gt;

&lt;p&gt;If we go down in the stack trace :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-lock
--reload
---_find_record
----lock (again, but another one)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So let's dive in the lock method :&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;lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;locking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Arel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"FOR UPDATE"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;locking&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
        &lt;span class="n"&gt;locking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Arel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"FOR UPDATE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;Arel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Nodes&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SqlLiteral&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;
        &lt;span class="n"&gt;locking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Arel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt; &lt;span class="n"&gt;locking&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="vi"&gt;@ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nodes&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Lock&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;locking&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;self&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 pretty simple. We add FOR UPDATE at the end of our Query if no lock option is set. &lt;br&gt;
And if there is one lock level we add it at the end of the SQL.&lt;/p&gt;

&lt;p&gt;And that's it now you know a bit more about Advisory locks and Row-Level Locking in Postgres :)!&lt;/p&gt;

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

&lt;p&gt;Now we know what advisory lock is with the pessimistic locking technique. But we also learn how to use the different Row-Level locking and what they are useful for.&lt;/p&gt;

&lt;p&gt;Advisory locks are powerful and are extensively used in GoodJob. They are a good way to ensure Consistency in your database without degrading too much.&lt;/p&gt;

&lt;p&gt;What could be interesting, though, is to understand the other row-level locking. And what they are useful for from my tests except for SELECT FOR UPDATE another one seems to not work as expected.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>database</category>
      <category>postgres</category>
    </item>
    <item>
      <title>State of Ruby : What version manager to use</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Wed, 11 Oct 2023 18:42:31 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/state-of-ruby-what-version-manager-to-use-4gbg</link>
      <guid>https://dev.to/yet_anotherdev/state-of-ruby-what-version-manager-to-use-4gbg</guid>
      <description>&lt;p&gt;I have asked on Twitter what was your favorite version manager for Ruby. &lt;/p&gt;

&lt;p&gt;The clear leader was Rbenv, ASDF, which was most of the comment for the last response; then we have RVM, but I will not consider it for the rest of this post because it is pretty obscure how it works :).&lt;/p&gt;

&lt;p&gt;Let's understand the critical difference between those and help you make some choices for your Ruby Version manager.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1692472247372378362-417" src="https://platform.twitter.com/embed/Tweet.html?id=1692472247372378362"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1692472247372378362-417');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1692472247372378362&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  Community
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    1.Rbenv
    2.ASDF
    3.Chruby
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, the Tweet shows that Rbenv is a great winner for the Ruby community. But it seems mainly because it is the goto solution.&lt;/p&gt;

&lt;p&gt;Nevertheless, this is a great thing because if you have an issue. It is more likely that you are one of many to have it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Versatility
&lt;/h2&gt;

&lt;p&gt;In terms of versatility, here is the leaderboard :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    1. ASDF
    2. Rbenv 
    3. ChRuby
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Indeed, ASDF enables you to manage your ruby version and supports many other languages and tools like nodejs. Moreover, you can add a plugin to it. &lt;/p&gt;

&lt;p&gt;Rbenv is also versatile, and you can add plugins; nevertheless, as its name suggests, you can only manage the ruby version. Rbenv and ASDF both use the same underlying gem, which is ruby-build. &lt;/p&gt;

&lt;p&gt;ChRuby is not extensible, and you can only manage Ruby with it. But it comes with ruby-mac, an excellent tool for installing ruby quickly on Mac.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. ChRuby
2. Rbenv
3. ASDF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Rbenv and Asdf are Shim. They act like a proxy for every call to Ruby. Inevitably, they are slower. &lt;br&gt;
Chruby does not provide that, and you need to use chruby-exec if you want to use the version managed by chruby.&lt;/p&gt;

&lt;h2&gt;
  
  
  Misc
&lt;/h2&gt;

&lt;p&gt;Moreover, both Rbenv and ASDF use ruby-build to compile and install ruby. Whereas chruby can use both ruby-build and ruby-install for new rubies installation.&lt;/p&gt;

&lt;p&gt;In addition, chruby is really simple to install if you are on Mac thanks to ruby-mac utility tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  And the winner is ?
&lt;/h2&gt;

&lt;p&gt;There is no such thing as a better version manager. It all depends on what you want to do.&lt;/p&gt;

&lt;p&gt;If you want a lightweight and quick version manager, use chruby. &lt;/p&gt;

&lt;p&gt;You have several choices if you want something with more extensibility and do not care about speed : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ASDF if you want to manage several other language than Ruby.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rbenv if you need a versatile version manager that manages only ruby&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is this &lt;a href="https://github.com/rbenv/rbenv/wiki/Comparison-of-version-managers"&gt;good resource&lt;/a&gt; that also talk about different ruby version manager from the Rbenv repository. With some links to benchmarks of ASDF and Rbenv.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Optimistic Locking (Rails internals again)</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Mon, 09 Oct 2023 04:21:07 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/optimistic-locking-rails-internals-again-3d67</link>
      <guid>https://dev.to/yet_anotherdev/optimistic-locking-rails-internals-again-3d67</guid>
      <description>&lt;p&gt;Recently, I had the opportunity to interview Ben Sheldon, the creator and maintainer of GoodJob.&lt;br&gt;
I often like to create an article to understand more about the gem we discover or rediscover in GemRubyShow. &lt;/p&gt;

&lt;p&gt;To tell you more about the gem, GoodJob is an ActiveJob Backend for your background Job. It works only with Rails and is backed by Postgres. It uses this interesting Pub/Sub mechanism of Postgres called &lt;code&gt;LISTEN NOTIFY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to learn more about GoodJob, you can listen to the &lt;a href="https://youtu.be/DJ9HIjLla_U?si=GO8yZZOzBhlkktB_"&gt;episode&lt;/a&gt; on YouTube. It was an excellent discussion with Ben Sheldon.&lt;/p&gt;

&lt;p&gt;Aside from the LISTEN/NOTIFY mechanism, another essential mechanism in GoodJob is advisory Locks. In this article, we will try to understand better what they are and how to use them in Rails.&lt;/p&gt;
&lt;h2&gt;
  
  
  Advisory Locks in Rails
&lt;/h2&gt;

&lt;p&gt;According to Postgres documentation, Advisory Locks are locks that have application-defined meanings. This is called Advisory Locks because it is up to you to use them correctly. They have a lot of benefits, avoid table bloat, and are automatically cleaned up by the server at the end of the session. &lt;/p&gt;

&lt;p&gt;There are two locking options in Rails : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimistic Locking &lt;/li&gt;
&lt;li&gt;Pessimistic Locking &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's go with Optimistic Locking in this article!&lt;/p&gt;
&lt;h2&gt;
  
  
  Optimistic Locking
&lt;/h2&gt;

&lt;p&gt;Let's say you have an application where you have users. &lt;br&gt;
Imagine you and your colleague want to update the name of a user at the same time in different processes. &lt;/p&gt;

&lt;p&gt;To avoid having an inconsistent database state, you can use Optimistic Locking. &lt;br&gt;
We call it Optimistic Locking because we go from the principle that conflict won't happen often. But if they happen, remember that handling them is up to you. &lt;/p&gt;

&lt;p&gt;Rails will support Optimistic Locking if you add a lock_version field to your table. &lt;br&gt;
For example, following our example with users if you create a users table :&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;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Schema&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;create_table&lt;/span&gt;&lt;span class="ss"&gt;:users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;force: &lt;/span&gt;&lt;span class="kp"&gt;true&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;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;integer&lt;/span&gt; &lt;span class="ss"&gt;:lock_version&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;Rails will automatically 'understand' that he has to use &lt;code&gt;Optimistic Locking&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Later, you want to update a user's name and do several operations at the same time in the same transaction (simulated by the sleep 20).&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;u1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&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="n"&gt;u1&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;name: &lt;/span&gt;&lt;span class="s1"&gt;'Lulu'&lt;/span&gt;&lt;span class="p"&gt;)&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;20&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;But your colleague wants to update the name and did it in another request simultaneously.&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;p1&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;last&lt;/span&gt;
&lt;span class="n"&gt;p1&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;name: &lt;/span&gt;&lt;span class="s1"&gt;'Lucky'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since you have put the lock_version, your Colleague will end up with an error &lt;code&gt;ActiveRecord::StaleObjectError&lt;/code&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Locking a row?
&lt;/h2&gt;

&lt;p&gt;It can be nice to know how Rails deal with this. Let's look at the code in  &lt;code&gt;activerecord/lib/active_record/locking/optimistic.rb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;for the update mechanism, well, you have a method called... &lt;code&gt;_update_row(attribute_names,attempted_action = "update")&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;A guard condition checks if locking is enabled and calls super if not:  &lt;code&gt;return super unless locking_enabled?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;How do you know if locking is enabled? Simple, we check the flag, and as we have said before, check if there is a &lt;code&gt;lock_version&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;This time the function speaks for itself:&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;# Returns true if the +lock_optimistically+ flag is set to true&lt;/span&gt;
  &lt;span class="c1"&gt;# (which it is, by default), and the table includes the&lt;/span&gt;
  &lt;span class="c1"&gt;# +locking_column+ column (defaults to +lock_version+).&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;locking_enabled?&lt;/span&gt;
    &lt;span class="n"&gt;lock_optimistically&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;columns_hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;locking_column&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;That's nice, but we need to find out how it knows that the object is stale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Down in the rabbit hole
&lt;/h2&gt;

&lt;p&gt;I have been down in the rabbit hole for you, and here is the complete (almost...) stack trace for the update of a row :&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="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;_update_row&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;_update_record&lt;/span&gt;
&lt;span class="o"&gt;---&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;
&lt;span class="o"&gt;----&lt;/span&gt;&lt;span class="n"&gt;exec_update&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;exec_delete&lt;/span&gt;
&lt;span class="o"&gt;-----&lt;/span&gt;&lt;span class="n"&gt;execute_and_clear&lt;/span&gt;
&lt;span class="o"&gt;------&lt;/span&gt;&lt;span class="n"&gt;exec_no_cache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be careful there are two exec_update methods (at least in the Postgres adapter code).&lt;/p&gt;

&lt;p&gt;For the next part of the article, suppose that your Isolation Level in your transaction/database allows concurrent reading.&lt;/p&gt;

&lt;p&gt;What will be returned from exec_no_cache is an instance of PG::result. In this instance, we have the &lt;code&gt;cmd_tuples&lt;/code&gt;; this &lt;code&gt;cmd_tuples&lt;/code&gt; contains the number of rows affected by your changes. By calling &lt;code&gt;yield&lt;/code&gt; on this instance of PG::result we will get &lt;code&gt;cmd_tuples&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's say you have read this row for the first time. lock_version was 0 for the two concurrent reads. But when you make any changes to your row, your lock_version is incremented : &lt;code&gt;self[locking_column] += 1&lt;/code&gt; in &lt;code&gt;_update_record&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Since the lock_version does not match the other write operation, no columns are updated for one of the transactions. This will raise an ActiveRecord::StaleObjectError according to this snippet of code :&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;if&lt;/span&gt; &lt;span class="n"&gt;affected_rows&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;1&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;StaleObjectError&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="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempted_action&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;There is no SQL locking mechanism as with Pessimistic Locking, which we will treat in another article. This is only at your application level.&lt;/p&gt;

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

&lt;p&gt;Now you are aware of Optimistic Lock and what is happening inside. With Optimistic locking, you take the bet that conflict won't happen a lot. &lt;/p&gt;

&lt;p&gt;And if they happen, you can resolve them efficiently (hopefully). It would be best to fix them yourself, so be careful when using optimistic locking.&lt;/p&gt;

&lt;p&gt;What is nice about Optimistic Locking is that it is Database-independent. But this can also be dangerous if you update a row with a custom SQL without incrementing the lock_version; you will end up with the same problem you try to solve with your Optimistic Lock.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>database</category>
      <category>postgres</category>
    </item>
    <item>
      <title>The Railtie, the Gem and the Middleware</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Tue, 26 Sep 2023 04:34:01 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/the-railtie-the-gem-and-the-middleware-3bic</link>
      <guid>https://dev.to/yet_anotherdev/the-railtie-the-gem-and-the-middleware-3bic</guid>
      <description>&lt;p&gt;I had the luck to interview Alexis Bernard about his works for my podcast. You should check this out and test one of his gems RoRvsWild.&lt;/p&gt;

&lt;p&gt;I was surprised when I installed the gem. The middleware was directly available in the rails Middlewares list without any action except: &lt;code&gt;bundle install&lt;/code&gt; and &lt;code&gt;rails s&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I wanted to understand how this is possible in Rails.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create our Gem
&lt;/h2&gt;

&lt;p&gt;Since a part the blog post's subject is creating a gem, let's create one. This is simple. You can follow the following simple steps : &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a gemspec file like the following
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#middlwar.gemspec&lt;/span&gt;
    &lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&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;s&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"middlwar"&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;version&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0.0.0"&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;summary&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"middl"&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authors&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Lucas Barret"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;files&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"lib/middlwar.rb"&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;ol&gt;
&lt;li&gt;&lt;p&gt;Create the code of your gem&lt;br&gt;
We will cover this in the second part of the article :)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build the gem with :&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem build my_middlware.gemspec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to have more information and dig even deeper, you can check in the guides of &lt;a href="https://guides.rubygems.org/make-your-own-gem/" rel="noopener noreferrer"&gt;rubygems website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Okay, since we know how to create the gem, we can know focus in the second part of the article how to create a middleware, use it as gem and fin insert it in rails Middlewares list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Gem code
&lt;/h2&gt;

&lt;p&gt;This is the problem of the eggs or the chicken. But here I will begin with my middleware code.&lt;/p&gt;

&lt;p&gt;To create a middleware for a rails app. All you have to do is creating a class that looks like this one :&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;MyMiddleware&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;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="vi"&gt;@app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;200&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;'I am a middleware'&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;This middleware get the HTTP request and always send back a response with HTTP code 200 and 'I am a middleware' as a body.&lt;/p&gt;

&lt;p&gt;But this won't appear in your app as is, you need to something more. Initialize your middleware and insert it in your rails app.&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;#lib/middlwar.rb&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyRailtie&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Railtie&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;insert_middleware&lt;/span&gt;
      &lt;span class="n"&gt;initializer&lt;/span&gt; &lt;span class="s2"&gt;"middle.configure_rails_initialization"&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;app&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unshift&lt;/span&gt; &lt;span class="no"&gt;MyMiddleware&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;insert_middleware&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 I want to put stress on is the Middleware part and especially the Railties.&lt;/p&gt;

&lt;p&gt;As usual, going through documentation cannot make anything worse—and going to the Rails &lt;a href="https://api.rubyonrails.org/classes/Rails/Railtie.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; espcially.&lt;/p&gt;

&lt;p&gt;We can learn that Railties are the core of the Rails Framework and can modify or extend the initialization process of Rails. &lt;/p&gt;

&lt;p&gt;Every significant component of Rails, like ActiveRecord, implements a Railtie. &lt;br&gt;
And they are responsible for their initialization.&lt;/p&gt;

&lt;p&gt;Could we say that Rails is a collection of useful gem that makes sense all together ? &lt;/p&gt;

&lt;p&gt;Whatever but here thanks to the railtie we initiatilize how own middleware/gem. &lt;/p&gt;

&lt;p&gt;I have define a class level method and then call it directly from inside my class. (Yeah remember even class code is executed when parsed by ruby interpreter).&lt;/p&gt;

&lt;p&gt;And that's it my middleware is instantiate and thanks to the &lt;code&gt;unshift&lt;/code&gt; method put at the top of the middleware list.&lt;/p&gt;
&lt;h2&gt;
  
  
  Put it in the Rails app
&lt;/h2&gt;

&lt;p&gt;This is maybe the simplest thing in this article : &lt;br&gt;
We will not push this gem on the Rubygems website, but we can include our gem code locally. &lt;/p&gt;

&lt;p&gt;In your gem file, you can add a line 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="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"my_middlware"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="s2"&gt;"../my_middlware"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now go for a &lt;code&gt;bundle install&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After that, you can load your middleware by restarting your server or just listing your server' Middlewares with &lt;code&gt;rails middleware&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap all the things up
&lt;/h2&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%2Fp36zq8rp2sufg4l0543o.jpg" 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%2Fp36zq8rp2sufg4l0543o.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's all folks, we have done a lot today. Creating a middleware extract it as a gem, and insert it in our Rails app as the first middleware. Eventually we even learn how to use local gem. &lt;/p&gt;

&lt;p&gt;I hope to see you for another article, in the mean time if you have question do not hesitate to comment :).&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>ActionPolicy , GraphQL and Rails</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Tue, 12 Sep 2023 10:12:26 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/actionpolicy-graphql-and-rails-43la</link>
      <guid>https://dev.to/yet_anotherdev/actionpolicy-graphql-and-rails-43la</guid>
      <description>&lt;p&gt;In the last &lt;a href="https://www.youtube.com/watch?v=K9wgJI-Dbic"&gt;episode&lt;/a&gt; of GemRubyShow, I had the opportunity to discuss Authorization with Vladimir Dementyev.&lt;br&gt;
I wanted to create an article showing you how simple yet powerful ActionPolicy the Gem he develops for Authorization.&lt;/p&gt;

&lt;p&gt;ActionPolicy was meant to be a part of Rails. This is why it is called &lt;code&gt;Action&lt;/code&gt; Policy. If you want to know the difference between Action and Active, we discuss that in the podcast with Vladimir.&lt;/p&gt;

&lt;p&gt;Even if ActionPolicy is Rails agnostic, this article will focus on implementing ActionPolicy in a simple Rails app using GraphQL. &lt;/p&gt;
&lt;h2&gt;
  
  
  Authorization
&lt;/h2&gt;

&lt;p&gt;I tweeted about authorization some time ago to remind myself of something important.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1696139578694857055-687" src="https://platform.twitter.com/embed/Tweet.html?id=1696139578694857055"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1696139578694857055-687');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1696139578694857055&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Nevertheless, what is Authorization? Let's try to answer that here :)&lt;/p&gt;

&lt;p&gt;As it is said in the ActionPolicy &lt;a href="https://actionpolicy.evilmartians.io/#/"&gt;documentation&lt;/a&gt; : &lt;code&gt;Authorization is the act of giving someone official permission to do something&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Moreover, there are several models of authorization for the most famous we have : &lt;br&gt;
    - DAC for Discretionary Access Control&lt;br&gt;
    - MAC for Mandatory Access Control&lt;br&gt;
    - RBAC for Role-Based Access Control&lt;br&gt;
    - ABAC for Attribute-Based Access Control&lt;/p&gt;

&lt;p&gt;Vladimir dive into these different models in his conference of 2018 &lt;/p&gt;
&lt;h2&gt;
  
  
  Authorization in GraphQL without ActionPolicy
&lt;/h2&gt;

&lt;p&gt;Let's say you have your Rails app with GraphQL installed. If you want to use authorization, you can use the graphql-ruby &lt;code&gt;authorized&lt;/code&gt; hook.  &lt;/p&gt;

&lt;p&gt;Let's say you have a mutation query and want to ensure that the current_user is authorized to perform this action, for example. &lt;br&gt;
For example, let's take a mutation that triggers a computation job that uses... I don't know GoodJob, for instance.&lt;br&gt;
If you want to perform authorization, you will do something that looks 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;module&lt;/span&gt; &lt;span class="nn"&gt;Mutations&lt;/span&gt; 
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TriggerJobMutation&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Mutations&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;BaseMutation&lt;/span&gt;

        &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Boolean&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;def&lt;/span&gt; &lt;span class="nf"&gt;authorized?&lt;/span&gt;
            &lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin?&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;resolve&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="no"&gt;MyJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_later&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;status: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;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;First, we have put the current_user in the context in the GraphQL controller (you can uncomment the line in the execute method).  &lt;/p&gt;

&lt;p&gt;Here, your authorized hook will be executed before the resolve method, and if it returns false at the end, the resolve method will not be executed. &lt;/p&gt;

&lt;p&gt;After that, you will add the method to your mutation_type 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="c1"&gt;#app/graphql/types/mutation_type.rb&lt;/span&gt;

&lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:trigger_job_mutation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;mutation: &lt;/span&gt;&lt;span class="no"&gt;Mutations&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TriggerJobMutation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is over... But as you can imagine, and as Vladimir said in his conference, this could be a bit better...&lt;/p&gt;

&lt;p&gt;Indeed, you will end up rewriting things everywhere. And we feel that it is not scalable. &lt;/p&gt;

&lt;p&gt;Let's see how ActionPolicy can help us avoid this cumbersome work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Call the Police?
&lt;/h2&gt;

&lt;p&gt;First, install the ActionPolicy gem in our Rails project &lt;code&gt;bundle add action_policy-graphql&lt;/code&gt;. And then install it; it is pretty standard with a gem: &lt;code&gt;bin/rails g action_policy:install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Using our previous example, You can create a policy that checks if your current_user is an admin. &lt;/p&gt;

&lt;p&gt;By default, &lt;code&gt;action_policy-graphql&lt;/code&gt; uses the &lt;code&gt;current_user&lt;/code&gt; defined in the context. Though remember to be sure you have a current_user in your context.&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;TriggerJobPolicy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationPolicy&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trigger?&lt;/span&gt;
    &lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin?&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 you want to add an authorization layer to this mutation,  in your &lt;code&gt;mutation_type.rb&lt;/code&gt;, add preauthorize to your field, and you are good to go.&lt;/p&gt;

&lt;p&gt;Why preauthorize and not authorize? After playing with the gem (or reading the doc :)). You can learn that &lt;code&gt;authorize&lt;/code&gt; will execute the query and then check the authorization. &lt;/p&gt;

&lt;p&gt;We want something else since if the user is not authorized to act, you want to prevent the action from being completed. &lt;/p&gt;

&lt;p&gt;To avoid that, you have the preauthorize hook, which will check the authorization before performing your mutation.&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/graphql/types/mutation_type.rb&lt;/span&gt;
&lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:trigger_job_mutation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;mutation: &lt;/span&gt;&lt;span class="no"&gt;Mutations&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TriggerJobMutation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;preauthorize: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;to: :trigger?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="no"&gt;TriggerJobPolicy&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it, I swear this is dead simple!&lt;/p&gt;

&lt;p&gt;Now, you have to test your app and your authorization layer. &lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Authorization
&lt;/h2&gt;

&lt;p&gt;Now, you want to test that your authorization is correctly set up. Nothing more simple, ActionPolicy brings helpers that you can add to your &lt;code&gt;rails_helper.rb&lt;/code&gt;. This includes matters for simplifying your test code.&lt;/p&gt;

&lt;p&gt;If you use RSpec, in your &lt;code&gt;rails_helper.rb&lt;/code&gt; file, you can add &lt;code&gt;require 'action_policy/rspec'&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="c1"&gt;# frozen_string_literal: true&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rails_helper'&lt;/span&gt;

&lt;span class="n"&gt;describe&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;'authorization'&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;:mutation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="sx"&gt;%(mutation {
            triggerJobMutation(input: {}) {
              status
            }
        })&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;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Lucas'&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="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;TestgoodjobSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;variables: &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="ss"&gt;context: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;current_user: &lt;/span&gt;&lt;span class="n"&gt;user&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="s1"&gt;'is authorized'&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;to&lt;/span&gt; &lt;span class="n"&gt;be_authorized_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:trigger?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'triggerJobMutation'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TriggerPolicy&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;We are production-ready now, right ?&lt;/p&gt;

&lt;h2&gt;
  
  
  That's all ?
&lt;/h2&gt;

&lt;p&gt;The actual strength of ActionPolicy lies in the multiple possibilities that another gem does not offer.&lt;/p&gt;

&lt;p&gt;Like caching, performance can be a huge concern. &lt;br&gt;
With ActionPolicy, you have caching at several levels (Instance, Thread, Cache Store). Moreover ActionPolicy uses PORO, which enables namespaces and is flexible. &lt;/p&gt;

&lt;p&gt;ActionPolicy is like a supercharged authorization gem and will ease your development. In this article, we barely scratched the surface of its capability. Yet, as we have seen, ActionPolicy is easy to use and straightforward.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>ActiveRecord Internals: You are still not ready</title>
      <dc:creator>Lucas Barret</dc:creator>
      <pubDate>Tue, 29 Aug 2023 05:08:49 +0000</pubDate>
      <link>https://dev.to/yet_anotherdev/activerecord-internals-you-are-still-not-ready-1705</link>
      <guid>https://dev.to/yet_anotherdev/activerecord-internals-you-are-still-not-ready-1705</guid>
      <description>&lt;p&gt;This is part 2 of a series of articles I have begun recently. I try to understand better Rails ActiveRecord and how this is designed internally.&lt;/p&gt;

&lt;p&gt;In the last article, we discussed reflection but did not dive into it.&lt;/p&gt;

&lt;p&gt;Now we still have some black spells to explore&lt;/p&gt;

&lt;p&gt;Oh yes, and if you like to learn or read about Rails, Ruby, databases, and a lot of tech-related stuff :&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep in Touch
&lt;/h3&gt;

&lt;p&gt;On Twitter/X : &lt;a href="https://twitter.com/yet_anotherDev"&gt;@yet_anotherDev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On Linkedin : Lucas Barret&lt;/p&gt;

&lt;p&gt;Mirror, who is the prettier?&lt;/p&gt;

&lt;p&gt;To remind you a bit of what we did in the last article. We have found the has_many method where we build reflection and add things to this reflection.&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;#rails/activerecord/associations.rb&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;has_many&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="n"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&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;extension&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;reflection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HasMany&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&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="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&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;extension&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;Reflection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_reflection&lt;/span&gt; &lt;span class="nb"&gt;self&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="n"&gt;reflection&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we did not answer the question of why we need this reflection. And what are reflections in fact? Let's risk ourselves to some mysterious coding concepts again.&lt;/p&gt;

&lt;p&gt;Reflection is an old concept, it can be described as the ability of some code to modify its code and structure at runtime. And this is key in metaprogramming. Without this concept, many cool things we like in Ruby and Rails would not exist.&lt;/p&gt;

&lt;p&gt;We need to retrieve dynamically the instance of the model associated with the current model. We need to define accessors for the associated model.&lt;/p&gt;

&lt;p&gt;If we get this example which is the same as our precedent article :&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;Medal&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
    &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:athlete&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;Athlete&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:medals&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we define these classes and associations. It is consistent to be able to access our medals from our athletes with something like this : athlete.medals to get all the medals of a specific athlete.&lt;/p&gt;

&lt;p&gt;This relies on two concepts one that we are discussing, Reflective programming, and another, which is Mixin, which we are going to study a bit later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflexive programming
&lt;/h2&gt;

&lt;p&gt;So even if you have declared your association in your class. You will be able to know what this association is at runtime and not before. This is compromising the fact to be able to do this :athlete.medals. How can you define code at runtime?&lt;/p&gt;

&lt;p&gt;For that, you'll need reflection; defining accessors at runtime after your ruby interpreter has effectively associated your two instances will not be an issue anymore.&lt;/p&gt;

&lt;p&gt;How you can do that? You define your active record and the name of the association. And thanks to that, if you respect Rails convention, we can retrieve the class of your active record and the table name. You can then define the readers and the writers for it at runtime.&lt;/p&gt;

&lt;p&gt;Let's see how :&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="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define_accessors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reflection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;mixin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generated_association_methods&lt;/span&gt;
      &lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reflection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;
      &lt;span class="n"&gt;define_readers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mixin&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="n"&gt;define_writers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mixin&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="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;define_readers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mixin&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="k"&gt;super&lt;/span&gt;

      &lt;span class="n"&gt;mixin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class_eval&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;CODE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__LINE__&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;
        def &lt;/span&gt;&lt;span class="si"&gt;#{&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;to_s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;singularize&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;_ids
          association(:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;).ids_reader
        end
&lt;/span&gt;&lt;span class="no"&gt;      CODE&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;define_writers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mixin&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="k"&gt;super&lt;/span&gt;

      &lt;span class="n"&gt;mixin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class_eval&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;CODE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__LINE__&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;
        def &lt;/span&gt;&lt;span class="si"&gt;#{&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;to_s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;singularize&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;_ids=(ids)
          association(:&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;).ids_writer(ids)
        end
&lt;/span&gt;&lt;span class="no"&gt;      CODE&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 code does exactly what we said for the ids but the idea is the same for the object instance accessors. You define dynamically thanks to the name of the association and the accessors to it.&lt;/p&gt;

&lt;p&gt;But then another pattern which is mysterious and obscure makes its appearance: mixin. There is also a bit of metaprogramming with class_eval that enables to define methods at runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mixin' all together
&lt;/h2&gt;

&lt;p&gt;The mixin pattern is needed for one reason. Ruby does not support multiple inheritance. And then, if you already have inherited from a class, you are doomed.&lt;/p&gt;

&lt;p&gt;But you can use a cool trick with the module and include keyword. This is the way of ruby to deal with multiple inheritance. There is this cool article by GeekForGeeks that you can check if you want.&lt;/p&gt;

&lt;p&gt;But to make it clearer :&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;##mixin_test.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Module1&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;module_method1&lt;/span&gt;
        &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s1"&gt;'module 1'&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;module&lt;/span&gt; &lt;span class="nn"&gt;Module2&lt;/span&gt;
    &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Module1&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;module_method2&lt;/span&gt;
        &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s1"&gt;'module 2'&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;ClassMixin&lt;/span&gt;
        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;class_method1&lt;/span&gt;
            &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="s1"&gt;'class mixin'&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="n"&gt;cla&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Class1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; 
&lt;span class="n"&gt;cla&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class_method1&lt;/span&gt;
&lt;span class="n"&gt;cla&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;module_method2&lt;/span&gt;
&lt;span class="n"&gt;cla&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;module_method1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ruby mixin_test.rb
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; class mixin
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; module 2
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; module 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All instance methods are available to the ruby class thanks to the mixin and the include keyword. And that's all folks!&lt;/p&gt;

&lt;p&gt;Now we have this, we can include our mixin in our Reflection, and once we will access our field, the method will be defined in the module, and we will be able to call them on the instance.&lt;/p&gt;

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

&lt;p&gt;Eventually, all this magic we experiment with Rails is, in fact, a good ol' trick and not sorcery. We need a lot of techniques, though, to make our beloved framework work, from reflection to mixin and macros.&lt;/p&gt;

&lt;p&gt;That's it with completing our first journey in the sorcery of rails. I hope you understand a bit better how active record association works.&lt;/p&gt;

&lt;p&gt;There is a lot to discover and understand; we have barely scratched the surface. But it feels good to understand a bit more about the technologies we use each day :).&lt;/p&gt;

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