<?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: VISHAL DEEPAK</title>
    <description>The latest articles on DEV Community by VISHAL DEEPAK (@vishaldeepak).</description>
    <link>https://dev.to/vishaldeepak</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%2F694570%2F0ecf63fb-f3eb-4c84-a1ac-9f6a321401ff.jpeg</url>
      <title>DEV Community: VISHAL DEEPAK</title>
      <link>https://dev.to/vishaldeepak</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vishaldeepak"/>
    <language>en</language>
    <item>
      <title>Run Rubcop on changed files with Git Status</title>
      <dc:creator>VISHAL DEEPAK</dc:creator>
      <pubDate>Mon, 04 Jul 2022 13:46:47 +0000</pubDate>
      <link>https://dev.to/vishaldeepak/run-rubcop-on-changed-files-with-git-status-5fef</link>
      <guid>https://dev.to/vishaldeepak/run-rubcop-on-changed-files-with-git-status-5fef</guid>
      <description>&lt;p&gt;Here me out before you think this is just another post which runs rubocop only on changed files. There's four things different here &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We run rubocop on newly added and renamed files as well. No need to stage them.(I found a few tutorials online that don't consider this)&lt;/li&gt;
&lt;li&gt;Skip deleted files&lt;/li&gt;
&lt;li&gt;Works on both staged and unstaged files with same code&lt;/li&gt;
&lt;li&gt;We use Git Status instead, for the sake of first point.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First let me give the command to you straight&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git status --porcelain | grep -E -v '^(D| D|RD)' | awk '{ print $NF }' | xargs rubocop 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lets break this down
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git status --porcelain&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This gets all the files that have been changed, added or deleted. &lt;code&gt;--porcelain&lt;/code&gt; is a easy to parse output format&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grep -E -v '^(D| D|RD)'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We remove all deleted files and renamed+deleted files if any. We dont want to run rubocop on our deleted files&lt;/p&gt;

&lt;p&gt;&lt;code&gt;awk '{ print $NF }'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This one is useful for one edge case. When we rename a staged file. For example if we rename a controller , the output of &lt;code&gt;git status --porcelain&lt;/code&gt; is as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;R  app/controllers/home_controller.rb -&amp;gt; app/controllers/house_controller.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;awk&lt;/code&gt; command  with &lt;code&gt;NF&lt;/code&gt; fetches only the last column&lt;/p&gt;

&lt;p&gt;&lt;code&gt;xargs rubocop&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;xargs run the rubocop command on each file&lt;/p&gt;

&lt;h2&gt;
  
  
  Alias it
&lt;/h2&gt;

&lt;p&gt;Adding alias requires a small modification to the script. This is because we dont want $NF to be expanded on declaration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias rubogit="git status --porcelain |  grep -E -v '^(D| D|RD)' | awk '{ print \$NF }' | xargs rubocop "
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me know if you had any edge case that didn't work with this command&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>rubocop</category>
    </item>
    <item>
      <title>Gotcha: Starting Jobs inside Transaction</title>
      <dc:creator>VISHAL DEEPAK</dc:creator>
      <pubDate>Wed, 29 Jun 2022 13:01:51 +0000</pubDate>
      <link>https://dev.to/vishaldeepak/gotcha-starting-jobs-inside-transaction-2joj</link>
      <guid>https://dev.to/vishaldeepak/gotcha-starting-jobs-inside-transaction-2joj</guid>
      <description>&lt;p&gt;Starting jobs inside an &lt;code&gt;Active Record Transaction&lt;/code&gt; can result in unexpected outputs. I've seen this happen multiple times in my career.&lt;/p&gt;

&lt;p&gt;Consider an example where we update a model and then send a third party API the updated model&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.transaction do
   david.withdrawal(100)
   mary.deposit(100)
   NotifyUser.perform_later david.id # Job to notify User
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lets assume that &lt;code&gt;NotifyUser&lt;/code&gt; sends a user their remaining balance in account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class NotifyUser &amp;lt; ApplicationJob
   queue_as :default
   def perform(user_id)
     user = User.find(user_id)
     ThirdPartyNotifier.notify(user)
   end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So you run this code in your local and it seems to work just fine. Money is withdrawn and the notification sends appropriate balance of the user. But alas, Later you find a bug in production, and weirdly sometimes the notification is correct, sometimes it not. &lt;/p&gt;

&lt;p&gt;The reason? The job sometimes runs before the transaction can even complete. Since we queue the job inside the transaction, there is a chance that the Job gets picked up before changes are committed to the database. The job then has old data. If you want to make sure the job send incorrect data every time in local add a &lt;code&gt;sleep(10)&lt;/code&gt; after &lt;code&gt;NotifyUser&lt;/code&gt;. This will ensure that job gets picked up before the transaction completes.&lt;/p&gt;

&lt;p&gt;The fix for this case is quite straightforward. Move the job call outside of the transaction&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.transaction do
   david.withdrawal(100)
   mary.deposit(100)
end
NotifyUser.perform_later david.id # Job to notify User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>rails</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Anonymous Controller tests for Request Spec</title>
      <dc:creator>VISHAL DEEPAK</dc:creator>
      <pubDate>Sun, 01 May 2022 18:38:15 +0000</pubDate>
      <link>https://dev.to/vishaldeepak/anonymous-controller-tests-for-request-spec-57ma</link>
      <guid>https://dev.to/vishaldeepak/anonymous-controller-tests-for-request-spec-57ma</guid>
      <description>&lt;p&gt;When developing your test suite via request spec, you may want to test functionality of controllers which do not have any actions. These controllers exist for sharing common functionality between multiple controllers. &lt;/p&gt;

&lt;p&gt;While writing these tests via &lt;code&gt;controller&lt;/code&gt; testing is more &lt;a href="https://relishapp.com/rspec/rspec-rails/v/3-6/docs/controller-specs/anonymous-controller"&gt;straight forward&lt;/a&gt;, I couldn't find any direct docs for such when using &lt;code&gt;request&lt;/code&gt; testing.&lt;/p&gt;

&lt;p&gt;Let's get to it then. Lets assume that we have a controller called &lt;code&gt;BaseController.rb&lt;/code&gt; that looks like the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class BaseController &amp;lt; ActionController::API
   private 
   def current_company
     return "forem" if request.headers['X-Api-Token'].present?
     return "external"
   end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the sake of the article we made a simple method that returns the current company as Forem if url, contains string 'forem' or else simply return "external"&lt;/p&gt;

&lt;p&gt;Lets test this out. In our rspec file, base_controller_spec.rb we use the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe 'Sets company', type: :request do
  before do
    klass = Class.new(BaseController) do
      def index
         json_response(current_company, :ok))
      end
    end
    stub_const('TestController', klass)

    Rails.application.routes.disable_clear_and_finalize = true 

    Rails.application.routes.draw do
      get '/test', to: 'test#index'
    end
  end

  after { Rails.application.reload_routes! }

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

&lt;/div&gt;



&lt;p&gt;Here's what we did&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the before block define a new anonymous Class. Animus classes are standard ruby classes without a constant assigned to them. They are very helpful for writing maintainable test.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Class.new(BaseController)&lt;/code&gt; is a form of inheritance in ruby. &lt;/li&gt;
&lt;li&gt;Inside this anonymous class we define a new method/action which  returns a simple json response. Via this response we can test if our base controller method works as expected.&lt;/li&gt;
&lt;li&gt;We use &lt;code&gt;stub_constant&lt;/code&gt; which helps us to prevent leaking of this class to other spec files. &lt;/li&gt;
&lt;li&gt;We preserve all original routes via &lt;code&gt;Rails.application.routes.disable_clear_and_finalize = true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Then create a new route endpoint to hit our test. This route points to our newly create controller action defined inside the anonymous class &lt;/li&gt;
&lt;li&gt;Once all our tests are run we make sure to return our routing table to its original state. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets get to our tests. Should be self explanatory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it 'when api token is given' do
  get '/test', headers: {'X-Api-Token': 'random_test'}
  expect(response.body).to eq("forem")
end

it 'when api token is not given' do
  get '/test', headers: {} 
  expect(response.body).to eq("external")
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple temple should hope you to solve more complex problems for testing base controllers. A full discussion can be &lt;a href="https://github.com/rspec/rspec-rails/issues/1596#issuecomment-834282306"&gt;found here&lt;/a&gt;&lt;/p&gt;

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