Enforcing coding guidelines using CircleCI and Rubocop

Being a rubyist we don’t just write code, we write beautiful code. But sometimes, in a hurry to complete the requirement some developers, especially new comer, might not follow the coding guidelines which would become headache later. Rubocop is here to rescue us from this scenario.

Let’s see how to integrate rubocop:

1. Add rubocop and generate config file:

      # Gemfile
      gem "rubocop", require: false
  
      # .rubocop.yml

      AllCops:
        Exclude:
          # You could specify set of files or dirs while you want to be ignored by rubocop
          - 'vendor/**/*'
          - 'spec/**/*'
          - 'config/**/*'
          - 'db/**/*'
          - 'lib/**/*'
          - 'bin/*'
          - 'Gemfile'
          - 'Gemfile.lock'
          - 'Rakefile'
      Documentation: # Disabling documentation cop
        Enabled: false
    

Here is the file where you can find list of cops that rubocop uses.

2. Run rubocop or through CircleCI:

      $ bundle exec rubocop -R

      Inspecting 47 files
        ...............................................

        47 files inspected, no offenses detected
   

where -R option make rubocop to run rails cops as well.

     #circle.yml

     test:
       post: 
         - bundle exec rubocop -R
   

This would run rubocop upon every commit on CircleCI. Though your test cases have been passed but if rubocop fails then your build fails.

Now let’s see how rubocop enforces you write to better & clean code:

Scenario-1: Using else with unless:

     # Before 
     unless @new_unit.open?
       'Unit is not available!!' 
     else 
       'Remark is empty!!' 
     end 
     
     # Comply to rubocop
     if @new_unit.open?
       'Remark is empty!!'
     else 
       'Unit is not available!!' 
     end
 

As a matter of fact, using else with if would make more sense than using with unless.

Scenario-2: Use next to skip iteration:

     # Before 
     @payment_vouchers.each do |pv|
       if pv.items.any?
         # code here
       end
     end
     
     # Comply to rubocop
     @payment_vouchers.each do |pv|
       next unless pv.items.any?
       # code here
     end
 

As you see after using next, code is more readable than before.

Rubocop not only highlights ruby code related issues but also pin points rails related issues as well.
Scenario-3: Use find_by instead of where.first:

     # Before 
     addr = addresses.where(type: 'primary').first
     
     # Comply to  rubocop
     addr = addresses.find_by(type: 'primary')
 

Scenario-4: Use proc instead of Proc.new:

     # Before 
     validates :address, presence: true, if: Proc.new{ |addr| add.type == 'primary' }
     
     # Comply to rubocop
     validates :address, presence: true, if: -> (addr) { addr.type == 'primary' }
 

Rubocop not only helps in covering all scenarios also insist on coding guidelines. Hope this would be helpful. Any feedback or suggestions are welcome.