<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Moiz Ali</title>
    <description>The latest articles on Forem by Moiz Ali (@moiz1524).</description>
    <link>https://forem.com/moiz1524</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%2F544480%2Fcac78710-3d33-44b3-9ed7-4efb2b2b3e17.png</url>
      <title>Forem: Moiz Ali</title>
      <link>https://forem.com/moiz1524</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/moiz1524"/>
    <language>en</language>
    <item>
      <title>How to initiate Refactoring?</title>
      <dc:creator>Moiz Ali</dc:creator>
      <pubDate>Tue, 24 May 2022 19:08:44 +0000</pubDate>
      <link>https://forem.com/moiz1524/how-to-initiate-refactoring-p4</link>
      <guid>https://forem.com/moiz1524/how-to-initiate-refactoring-p4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;4 years later, when I started programming I used to write code and just care about the results mainly &lt;strong&gt;Its working How it's intended to be stance&lt;/strong&gt;. But as time passed I realized that whenever I want to add a new functionality within, it becomes nearly impossible for me. &lt;/p&gt;

&lt;p&gt;However Rails defaults enable us to stick with OOP principles and good practices, but as codebase grows you have to be a champion to hold up things properly!&lt;/p&gt;

&lt;p&gt;So I have to compromise and search for escape routes. My bad. Being pro-active and habit of thinking to extend the genre is what I'm missing. By time I learnt from different experiences, features, other people's code and mainly from Google (How can I miss this!)&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we need Refactoring?
&lt;/h2&gt;

&lt;p&gt;As I described above that it becomes hard to extend features, add new stuff but mainly you lose the control of your codebase. You become a slave of an unknown compelling force established within your app. Produced by your bad code and mis management.&lt;/p&gt;

&lt;p&gt;Just think about big tech giants and social media apps, how code is being managed and scaled to reach a bigger audience. You'll get the answer for sure!&lt;/p&gt;

&lt;h2&gt;
  
  
  Jumping into the Playground
&lt;/h2&gt;

&lt;p&gt;Today I'm going to share my initial 5 steps approach to refactor a bad piece of code. It can be a starting point for those who don't have an idea about &lt;em&gt;Where to start?&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Lets start this!&lt;/p&gt;

&lt;p&gt;As an example, we'll discuss this controller action in Rails which have code smells. It enables admin to assign user a specific subscription membership group.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fnISP8TU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ckc924bsjb07p8gvrsh7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fnISP8TU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ckc924bsjb07p8gvrsh7.png" alt="Bad piece" width="880" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;h3&gt;
  
  
  1: Dry run each line of code, understand meanings?
&lt;/h3&gt;

&lt;p&gt;I have added comments against each line. See&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KYLYoRie--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d54d1cwfl5j57nhqud0n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KYLYoRie--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d54d1cwfl5j57nhqud0n.png" alt="Code with comments" width="880" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;h3&gt;
  
  
  2: Identify responsibilities with Divide &amp;amp; Conquer rule
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Authorization check for user's role&lt;/li&gt;
&lt;li&gt;Query user from db and figure out user old membership and new group for further addition&lt;/li&gt;
&lt;li&gt;Update user with new attrs&lt;/li&gt;
&lt;li&gt;Send membership email&lt;/li&gt;
&lt;li&gt;Perform subscription expiry job&lt;/li&gt;
&lt;li&gt;Handle failure case of #update&lt;/li&gt;
&lt;li&gt;Handle failure case of authorization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3: Extract methods by Single Responsibility Principle
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;The single-responsibility principle (SRP) is a computer-programming principle that states that every module, class or function in a computer program should have responsibility over a single part of that program's functionality, and it should encapsulate that part.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OckHXYhS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gyhc2l5ob88ecy8r5335.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OckHXYhS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gyhc2l5ob88ecy8r5335.png" alt="Single Responsibility Principle" width="880" height="821"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In accordance with responsibilites obtained in Step 2. I've added seperate methods. Each doing its own thing.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;check_user_role!&lt;/code&gt; depicts authorization check, continue only if user is an &lt;em&gt;admin&lt;/em&gt; otherwise redirect. The ! at the end describes that its going to follow-up immediately&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grab_user_and_associated_group&lt;/code&gt; find user, get membership names, group and expiry date. Here I switched local variables with instance variables to manipulate them among micro actions. Provided the fact we can also use them inside views.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;user_params&lt;/code&gt; prepares hash to pass inside update call&lt;/p&gt;

&lt;p&gt;&lt;code&gt;update_user&lt;/code&gt; updates user and call &lt;code&gt;forward_emails_then_set_job&lt;/code&gt;. It has an &lt;code&gt;else&lt;/code&gt; case to describe if something goes wrong.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;forward_email_then_set_job&lt;/code&gt; calls mailer and job classes respectively. For sake of simplicity, I'm skipping discussion for them!&lt;/p&gt;

&lt;p&gt;Notice about usage of redirect_back in this context, instead of using &lt;code&gt;redirect_to&lt;/code&gt; with &lt;code&gt;request.referrer&lt;/code&gt; You can find it &lt;a href="https://apidock.com/rails/v5.0.0.1/ActionController/Redirecting/redirect_back"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4: Filter out performance gaps and fill them
&lt;/h3&gt;

&lt;p&gt;If you notice down, there is a performance gap inside &lt;code&gt;forward_email_then_set_job&lt;/code&gt;. The problem is &lt;code&gt;deliver_now&lt;/code&gt; and &lt;code&gt;perform_now&lt;/code&gt;. When we have a queue backend like Sidekiq in place, its essential to configure queues which can hold up jobs to perform one by one. &lt;code&gt;deliver_now&lt;/code&gt; halts this priority queue and we can face the situations where jobs received at same time instant would be dropped, thus creating load on queue backend. &lt;/p&gt;

&lt;p&gt;For the solution, I've used &lt;code&gt;deliver_later&lt;/code&gt; and &lt;code&gt;perform_later&lt;/code&gt; which takes care of priority queue. Jobs are processed one by one, providing minimal drop chances and optimized queue backend&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fMp6Q1IY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ra7rmyns7g6vylnnok6m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fMp6Q1IY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ra7rmyns7g6vylnnok6m.png" alt="Performance issue" width="880" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;h3&gt;
  
  
  5: Put all pieces and ask yourself &lt;em&gt;Is it improved&lt;/em&gt;?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a_KrhElA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ro8bkz5bjrz97za16t5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a_KrhElA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ro8bkz5bjrz97za16t5.png" alt="Put all together" width="880" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The answer can be Yes or No. But the new version would be better than worst. A stable form!&lt;/p&gt;

&lt;p&gt;Refactoring is costly if not done from the start. Its a habit towards self improvisation and better understanding of code.&lt;/p&gt;

&lt;p&gt;I haven't came up with a perfect version. There are certain improvements we can do here. I would like to hear from you guys. Do Share and Like if you find it useful ..&lt;/p&gt;

</description>
      <category>refactorit</category>
      <category>rails</category>
      <category>beginners</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Why you're not Productive?</title>
      <dc:creator>Moiz Ali</dc:creator>
      <pubDate>Sat, 14 May 2022 19:09:22 +0000</pubDate>
      <link>https://forem.com/moiz1524/why-youre-not-productive-enb</link>
      <guid>https://forem.com/moiz1524/why-youre-not-productive-enb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As my software engineering journey progressed, I found mistakes and short comings that slowed and lowered down my productivity bar. Years before, it seemed no problem &lt;br&gt;
until I put myself through a &lt;strong&gt;Self Assessment process&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Today I would like to share those common Slippery Patches so you can get a feel and prepare yourself against them on the first hand&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  False Initialization (Lose the moment)
&lt;/h2&gt;

&lt;p&gt;Being a human, we respond to everything that comes in for us. Either its a social interaction or work specific.&lt;/p&gt;

&lt;p&gt;Region of time lapse must be ideal. As a developer, if a task is assigned to you, there should be a plan to implement and get along to finish line. &lt;/p&gt;

&lt;p&gt;Time can never be infinite, so if you initiate stuff at the right time the possibility ratio of success broaden itself. You definitely get a chance to submit work at time. Using 8 hrs to complete work daily is an Art. Undoubtedly, you'll learn this by time and experience.&lt;/p&gt;

&lt;p&gt;If you are unable to do so, time is near when you get stuck in Late night spendings for work and get your ass safe!&lt;br&gt;
This directly cast a negative impact on your personal life. Either your family, friends or your own space. &lt;/p&gt;

&lt;h2&gt;
  
  
  Lack of Prioritization
&lt;/h2&gt;

&lt;p&gt;Active and Passive are two natures that live inside developers. The person with first always know what's ahead, he/she plans and set up their schedulers while others just procrastinate. &lt;/p&gt;

&lt;p&gt;This practice leads towards No Goal Achievement or Low Progess Levels. Also a common problem of those who are struggling to find a better fit between Work and Life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Useless Internet Surfing
&lt;/h2&gt;

&lt;p&gt;Developers love to connect with global world and its really awesome. But surf wisely not blindly. If you're use to scroll feed of your favorite app, many times in an hour. Chances are there to spoil your productivity bar. By surfing wisely I mean to surf in a specific time to chill and relieve stress. Watch podcasts, read books or watch a movie when you feel tired or frustrated!&lt;/p&gt;

&lt;p&gt;So thats all for now!!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you faced these issues&lt;/strong&gt;? or &lt;strong&gt;struggling to find a better fit&lt;/strong&gt;. Let me know inside comments so we can tie threads and learn together!&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>coding</category>
      <category>development</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Magical Bulk Insertion in Rails 6</title>
      <dc:creator>Moiz Ali</dc:creator>
      <pubDate>Tue, 10 May 2022 03:53:17 +0000</pubDate>
      <link>https://forem.com/moiz1524/magical-bulk-insertion-in-rails-6-4k44</link>
      <guid>https://forem.com/moiz1524/magical-bulk-insertion-in-rails-6-4k44</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In modern apps we mostly have a requirement which allows user to perform bulk actions. Like insertion of records is the one.&lt;/p&gt;

&lt;p&gt;On the first take you would come up with this version&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8vPtIQ6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqwraqwalme1f7816d6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8vPtIQ6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqwraqwalme1f7816d6c.png" alt="Image description" width="880" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problematic Region
&lt;/h2&gt;

&lt;p&gt;So what the hack? Above code is a classic situation of multiple sql insert calls, each for a movie creation. This yields slow performance, eventually bad code! &lt;/p&gt;

&lt;h2&gt;
  
  
  Workaround in Oldies
&lt;/h2&gt;

&lt;p&gt;If you're running on Rails 5 and older versions, you might face the situtation where writing raw customized SQL or using gems like &lt;a href="https://github.com/zdennis/activerecord-import"&gt;activerecord-import&lt;/a&gt; is the final option you left with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Magic of Rails 6
&lt;/h2&gt;

&lt;p&gt;But once you're up and running here, there is a method for you, built out of the box namely &lt;strong&gt;insert_all&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pick your wand and lets get started!&lt;/p&gt;

&lt;p&gt;*We are discussing a Car model here&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J5elHJ6L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ijp0tx8cy5u039hlkoq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J5elHJ6L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ijp0tx8cy5u039hlkoq1.png" alt="Image description" width="880" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation here: &lt;a href="https://apidock.com/rails/v6.0.0/ActiveRecord/Persistence/ClassMethods/insert_all"&gt;https://apidock.com/rails/v6.0.0/ActiveRecord/Persistence/ClassMethods/insert_all&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do you find it useful? Let me know inside comments!&lt;br&gt;
Follow me for more interesting snacks.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>development</category>
      <category>sql</category>
    </item>
    <item>
      <title>5 Surprising ways to use Rails console</title>
      <dc:creator>Moiz Ali</dc:creator>
      <pubDate>Sat, 07 May 2022 20:06:18 +0000</pubDate>
      <link>https://forem.com/moiz1524/5-surprising-ways-to-use-rails-console-33ie</link>
      <guid>https://forem.com/moiz1524/5-surprising-ways-to-use-rails-console-33ie</guid>
      <description>&lt;p&gt;While running on Rails, there's been hardly a day when you don't pull up rails console. Having basic mode and usage is fine but to spice up things a little bit I would like to share some tricks in this regard.&lt;/p&gt;

&lt;h2&gt;
  
  
  View Tables
&lt;/h2&gt;

&lt;p&gt;Just run this command and get a glimpse of tables&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--szdsCOAF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/900maaq4yvo76lie5fnk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--szdsCOAF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/900maaq4yvo76lie5fnk.png" alt="Image description" width="880" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sandbox Mode
&lt;/h2&gt;

&lt;p&gt;You can enable sandbox mode, so that commands are rolled back once you exit&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ilxNFiHP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xktujzs6kb28qvonmk7o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ilxNFiHP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xktujzs6kb28qvonmk7o.png" alt="Image description" width="880" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Make HTTP Requests
&lt;/h2&gt;

&lt;p&gt;Being lazy to hit a route through chrome or any other browser, just play with &lt;strong&gt;app&lt;/strong&gt; object's methods!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xs9IAQyr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/upiw32a2xca5ohnhrdhi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xs9IAQyr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/upiw32a2xca5ohnhrdhi.png" alt="Image description" width="880" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Locate Method Source
&lt;/h2&gt;

&lt;p&gt;Its a kindof search feature that a code editor also offers, but helpful one for the rubyists&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ajvNqduh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v8c7e2r3e3d66lq46p6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ajvNqduh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v8c7e2r3e3d66lq46p6g.png" alt="Image description" width="880" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Block Returned Output
&lt;/h2&gt;

&lt;p&gt;If you're annoyed from the return value by iterators and other structures, this will let you cool down!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9AsP1J9Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ij1768yev9de4stb91yi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9AsP1J9Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ij1768yev9de4stb91yi.png" alt="Image description" width="880" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Does it worth time saving?. Let me know inside comments. &lt;br&gt;
Make sure to Love and follow &lt;a class="mentioned-user" href="https://dev.to/moiz1524"&gt;@moiz1524&lt;/a&gt; &lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>codenewbie</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why you should write good commit messages?</title>
      <dc:creator>Moiz Ali</dc:creator>
      <pubDate>Thu, 14 Apr 2022 00:21:45 +0000</pubDate>
      <link>https://forem.com/moiz1524/why-you-should-write-good-commit-messages-dmj</link>
      <guid>https://forem.com/moiz1524/why-you-should-write-good-commit-messages-dmj</guid>
      <description>&lt;p&gt;I read a lot of posts that describe how to write awesome commit messages?. This is an undeniable fact that every developer needs to do it for some or more reasons. It’s a habit, hard to adopt but once gained, it returns a fruitful response. On professional grounds, I have sensed my top 3 reasons for this:&lt;/p&gt;

&lt;h2&gt;
  
  
  Codebase Versioning
&lt;/h2&gt;

&lt;p&gt;Your commit resolves to a particular version of the codebase. It can include a bug fix or a new feature or an enhancement. All this means that a change has been introduced. To identify this, there must be a meaningful one-liner sentence without digging into details. Viewing and reading code snippets within a bunch of files is not cool at first! Think about the scenario when you are chasing a buggy commit to extract out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back &amp;amp; Forth Tracking
&lt;/h2&gt;

&lt;p&gt;When a team collaborates on a project, they have assigned their specific branches. One’s scope of work will decide how many features are required? Lines of code and actions they need to integrate? During work if a bad commit is introduced and being pushed to the stack by upcoming ones, it becomes hard to trace the buggy part if you don’t have a relevant trail commit message. Always Remember! Healthy and appropriate commit history for each iteration provide a backtrace, resolution in relevance to bug!&lt;/p&gt;

&lt;h2&gt;
  
  
  Seamless PR reviews
&lt;/h2&gt;

&lt;p&gt;PR helps to understand the state in which code has been built, changes integration and avoids code smells. PR Review is a challenging task. You have to analyze code and report smells when they exist. Having a low discouraged commit history results in poor state lookup for a module or piece of code. As PRs are a way of getting response&lt;/p&gt;

&lt;p&gt;Hungry to learn about writing commit messages? Check this &lt;a href="https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages/"&gt;link&lt;/a&gt; from freeCodeCamp&lt;/p&gt;

&lt;p&gt;Happy committing !!&lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>development</category>
      <category>github</category>
      <category>git</category>
    </item>
    <item>
      <title>Facebook Data Deletion Request Callback</title>
      <dc:creator>Moiz Ali</dc:creator>
      <pubDate>Wed, 10 Feb 2021 20:27:40 +0000</pubDate>
      <link>https://forem.com/moiz1524/facebook-data-deletion-request-callback-jfk</link>
      <guid>https://forem.com/moiz1524/facebook-data-deletion-request-callback-jfk</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;INTRODUCTION:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In order to provide user more control over data and to protect data privacy norms, facebook gives option to remove all data consumed by the apps and integrations. A common use case scenario is When a user authenticates with Facebook to use application's services, his profile details are stored by the app. User can send a request to your app to delete his facebook consumed data afterwards.&lt;/p&gt;

&lt;p&gt;You can check more about it &lt;a href="https://developers.facebook.com/docs/development/create-an-app/app-dashboard/data-deletion-callback/"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why is it necessary?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As a developer we need to implement a Data Deletion Request callback url to get our app passed for Facebook compliance when user request to delete his/her data. This is mandatory as per new data privacy policy, GDPR. Also we can't submit our app for Review and switch to Live mode without implementing it&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Implement the Callback URL:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We have to make a POST web API endpoint on our server, where we'll receive requests from Facebook. Our endpoint must be &lt;strong&gt;HTTPS&lt;/strong&gt; enabled and preserve the functionality to parse signed request token sent by Facebook and take further actions to delete user's data.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Actual Code in Rails:&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  def facebook_user_deletion
    signed_request = params['signed_request']
    data = parse_fb_signed_request(signed_request)

    # Do data deletion stuff then
    user = User.find_by(uid: data['user_id'])
    user.destroy

    # Return tracking url and code to Facebook
    data = { url: "#{ENV['APP_HOST_URL']}/deletion_status?id=del_#{user.id}", confirmation_code: "del_#{user.id}" }

    respond_to do |format|
      format.json { render :json =&amp;gt; data }
    end
  end

  def parse_fb_signed_request(signed_request)
    encoded_sig, payload = signed_request.split('.', 2)
    secret = ENV['FACEBOOK_SECRET_ID']

    # Decode the data
    decoded_sig = Base64.urlsafe_decode64(encoded_sig)
    data = JSON.load(Base64.urlsafe_decode64(payload))

    # Create the HMAC signature
    expected_sig = OpenSSL::HMAC.digest("SHA256", secret, payload)

    if decoded_sig != expected_sig
      puts 'Bad Signed JSON signature!'
      return nil
    end

    data
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;EXPLANATION:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Our &lt;code&gt;facebook_user_deletion&lt;/code&gt; method is the endpoint where request is received. Firstly we are getting signed_request token from the params hash and passing it to our &lt;code&gt;parse_fb_signed_request&lt;/code&gt; method as a parameter which will parse it and return user's data JSON object 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;{
   "algorithm": "HMAC-SHA256",
   "expires": 1291840400,
   "issued_at": 1291836800,
   "user_id": "218471"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this object user_id is our relevant field which we are using to find the user and destroy it.&lt;/p&gt;

&lt;p&gt;After that we are returning a JSON response object to Facebook, which has url and confirmation code key-value pairs. Basically this url exists on our server in the form of a webpage where user can check status of his request by using his own confirmation code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I am using some interpolation inside values to dynamically inject user ids. Also ENV['APP_HOST_URL'] is an environment variable which holds my app's default host url.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In &lt;code&gt;parse_fb_signed_request&lt;/code&gt; method we split the token into two parts with reference to dot(.) to obtain encoded signature and payload. &lt;br&gt;
Then we get app's facebook secret id which will be used to construct the expected signature&lt;/p&gt;

&lt;p&gt;For decoding signature and payload I've used &lt;code&gt;Base64.urlsafe_decode64&lt;/code&gt; method, afterwards decoded payload &lt;br&gt;
is loaded into JSON object and stored in &lt;code&gt;data&lt;/code&gt; variable&lt;/p&gt;

&lt;p&gt;You can learn more about Base64 and JSON.load methods here:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://ruby-doc.org/stdlib-2.6.3/libdoc/base64/rdoc/Base64.html"&gt;Base64&lt;/a&gt;&lt;br&gt;
&lt;a href="https://apidock.com/ruby/JSON/load"&gt;JSON.load&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After that we are creating an HMAC signature using SHA256 algorithm, app's secret and payload object. Finally an &lt;code&gt;If&lt;/code&gt; conditional block confirms the signature by comparing the decoded and newly created signature, thus returning &lt;code&gt;nil&lt;/code&gt; object when block fails otherwise it returns data&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Add API endpoint as Callback in Facebook Project App:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Go to &lt;a href="https://developers.facebook.com/apps/"&gt;App Dashboard&lt;/a&gt; &amp;gt; Products &amp;gt; Facebook Login &amp;gt; Settings &amp;gt; Data Deletion Requests&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Testing your Callback:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Log in to your app with Facebook Login.&lt;/li&gt;
&lt;li&gt;Go to &lt;a href="https://www.facebook.com/settings?tab=applications"&gt;app settings&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Remove your app.&lt;/li&gt;
&lt;li&gt;In the Removed section, click on your app.&lt;/li&gt;
&lt;li&gt;Request data deletion from the app card.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>facebook</category>
      <category>deletion</category>
      <category>callback</category>
      <category>rails</category>
    </item>
  </channel>
</rss>
