<?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: Gideon Kimutai</title>
    <description>The latest articles on DEV Community by Gideon Kimutai (@gr1d99).</description>
    <link>https://dev.to/gr1d99</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%2F119524%2F110d09e9-fe89-479a-87b9-4e94b1c8c94f.jpeg</url>
      <title>DEV Community: Gideon Kimutai</title>
      <link>https://dev.to/gr1d99</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gr1d99"/>
    <language>en</language>
    <item>
      <title>Enforcing Unique Constraints Across Multiple Columns in Ruby on Rails</title>
      <dc:creator>Gideon Kimutai</dc:creator>
      <pubDate>Thu, 05 Jan 2023 03:41:34 +0000</pubDate>
      <link>https://dev.to/gr1d99/enforcing-unique-constraints-across-multiple-columns-in-ruby-on-rails-hjf</link>
      <guid>https://dev.to/gr1d99/enforcing-unique-constraints-across-multiple-columns-in-ruby-on-rails-hjf</guid>
      <description>&lt;p&gt;Today, we are going to look into validating uniqueness of a given column based on two or more columns on a database level for data integrity.&lt;/p&gt;

&lt;p&gt;Lets create a simple e-commerce app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails new e-com &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgresql &lt;span class="nt"&gt;--api&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will create 4 models &lt;strong&gt;Product, Cart, CartItem, Sku&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g model sku no:string

rails g model product name:string sku:references

rails g model cart

rails g model cart_item quantity:integer cart:references sku:references product:references

rake db:create
rake db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! We now have our models&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding Associations&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Product&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Belongs to an &lt;strong&gt;sku&lt;/strong&gt; and an &lt;strong&gt;sku&lt;/strong&gt; has one &lt;strong&gt;product&lt;/strong&gt;, in short it has &lt;strong&gt;one_to_one&lt;/strong&gt; relationship.
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:sku&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sku&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Has one product
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sku&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_one&lt;/span&gt; &lt;span class="ss"&gt;:product&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cart&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Has many &lt;strong&gt;cart items&lt;/strong&gt;, and a &lt;strong&gt;CartItem&lt;/strong&gt; belongs to a cart. The association is &lt;strong&gt;one_to_many&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cart&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:cart_items&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CartItem&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Belongs to &lt;strong&gt;cart, product, and sku&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CartItem&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:cart&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:sku&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:product&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Goal&lt;/strong&gt;&lt;br&gt;
Our goal is to have one &lt;strong&gt;cart_item&lt;/strong&gt; of a given &lt;strong&gt;product_id&lt;/strong&gt; within a given &lt;strong&gt;cart&lt;/strong&gt; and also ensure that the &lt;strong&gt;sku_id&lt;/strong&gt; is unique.&lt;/p&gt;

&lt;p&gt;If we create a &lt;strong&gt;cart_item&lt;/strong&gt; record with &lt;strong&gt;cart_id=1, product_id=1 and sku_id=1&lt;/strong&gt;, then we should never have another record with &lt;strong&gt;cart_id=1, product_id=1 and sku_id=1&lt;/strong&gt;. Make sense?&lt;/p&gt;

&lt;p&gt;Let's see it in action, fire up rails console&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Add records&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Sku&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;

&lt;span class="no"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;sku: &lt;/span&gt;&lt;span class="no"&gt;Sku&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="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Product 1'&lt;/span&gt;

&lt;span class="no"&gt;Cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumyadr9u0odkzegr6bpd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumyadr9u0odkzegr6bpd.png" alt="Image description" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create First &lt;strong&gt;CartItem&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;CartItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;product: &lt;/span&gt;&lt;span class="no"&gt;Product&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="ss"&gt;sku: &lt;/span&gt;&lt;span class="no"&gt;Product&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;sku&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;cart: &lt;/span&gt;&lt;span class="no"&gt;Cart&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="ss"&gt;quantity: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create another &lt;strong&gt;CartItem&lt;/strong&gt; record.&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;CartItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt; &lt;span class="ss"&gt;product: &lt;/span&gt;&lt;span class="no"&gt;Product&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="ss"&gt;sku: &lt;/span&gt;&lt;span class="no"&gt;Product&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;sku&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;cart: &lt;/span&gt;&lt;span class="no"&gt;Cart&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="ss"&gt;quantity: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pssst!&lt;/strong&gt; This shouldn't work, we run the same command, now we have 2 cart items with the same &lt;strong&gt;cart_id, product_id, and sku_id&lt;/strong&gt;. How can we fix this?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Delete all cart items&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;CartItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy_all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add &lt;strong&gt;unique index constraint&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g migration add_unique_index_to_cart_items
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open the migration file and add the statement below.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;add_index&lt;/span&gt; &lt;span class="ss"&gt;:cart_items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:cart_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:sku_id&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;unique: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run migrations&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rake db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open rails console and create 2 cart items with the same &lt;strong&gt;cart_id, product_id and sku_id&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CartItem.create product: Product.first, sku: Product.first.sku, cart: Cart.first, quantity: 1

CartItem.create product: Product.first, sku: Product.first.sku, cart: Cart.first, quantity: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We did it! you will notice that the second command is rolled back! This is because of the constrain that we added.&lt;/p&gt;

&lt;p&gt;Now lets validate by adding a different product.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sku.create

Product.create sku: Sku.last, name: 'Product 2'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the above product to the same cart&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CartItem.create product: Product.last, sku: Product.last.sku, cart: Cart.first, quantity: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above works because, the &lt;strong&gt;product_id&lt;/strong&gt; and &lt;strong&gt;sku_id&lt;/strong&gt; are unique, even though they are in the same cart.&lt;/p&gt;

&lt;p&gt;Query &lt;strong&gt;Cart&lt;/strong&gt; items&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;Cart&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;cart_items&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnlvic5upuj5eqmg5l11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnlvic5upuj5eqmg5l11.png" alt="Image description" width="800" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do not rely on model level validations, as they can be bypassed.&lt;/li&gt;
&lt;li&gt;Supplement model level validations with database level validations.&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Ongoing E-commerce shop API(Ruby on Rails)</title>
      <dc:creator>Gideon Kimutai</dc:creator>
      <pubDate>Fri, 23 Dec 2022 15:36:43 +0000</pubDate>
      <link>https://dev.to/gr1d99/ongoing-e-commerce-shop-apiruby-on-rails-4md0</link>
      <guid>https://dev.to/gr1d99/ongoing-e-commerce-shop-apiruby-on-rails-4md0</guid>
      <description>&lt;p&gt;Follow series &lt;a href="https://www.youtube.com/playlist?list=PL3tDRmVst0DdULAoasDu3teE-redNxEiQ"&gt;here&lt;/a&gt; &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Deploy Ruby on Rails App on AWS Part 1</title>
      <dc:creator>Gideon Kimutai</dc:creator>
      <pubDate>Fri, 17 Jul 2020 04:27:59 +0000</pubDate>
      <link>https://dev.to/gr1d99/deploy-ruby-on-rails-app-on-aws-part-1-57i9</link>
      <guid>https://dev.to/gr1d99/deploy-ruby-on-rails-app-on-aws-part-1-57i9</guid>
      <description>&lt;p&gt;Part 1: Setting up ec2 instance: &lt;a href="https://youtu.be/-abUqrmB7Ns?list=PL3tDRmVst0DdgRzuIuN5dVb9uZtslUlLB"&gt;https://youtu.be/-abUqrmB7Ns?list=PL3tDRmVst0DdgRzuIuN5dVb9uZtslUlLB&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More parts to come.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>aws</category>
      <category>nginx</category>
    </item>
    <item>
      <title>Integrate warden to Ruby on Rails API only app(Very Basic)</title>
      <dc:creator>Gideon Kimutai</dc:creator>
      <pubDate>Sat, 28 Dec 2019 18:27:09 +0000</pubDate>
      <link>https://dev.to/gr1d99/integrate-warden-to-ruby-on-rails-api-only-app-very-basic-5hdl</link>
      <guid>https://dev.to/gr1d99/integrate-warden-to-ruby-on-rails-api-only-app-very-basic-5hdl</guid>
      <description>&lt;p&gt;Here is the link to the tutorial I made: &lt;a href="https://www.youtube.com/playlist?list=PL3tDRmVst0DdPIvIEn5lmCmAbxGXojyQo"&gt;start now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>authentication</category>
      <category>warden</category>
    </item>
  </channel>
</rss>
