Rubocop is great! Nothing is better than consistency when learning a new coding language, and the rigidity of rubocop was a real help when figuring out the most idomatic way to write something in ruby.

However; many rules are idealistic, and are not suited to production or "real-world" environment.

Thankfully we can leverage rubocop with our own style, I've detailed some of my exceptions below.

Please note: with the exception of double quotes and the empty lines, the following rules only disable the behaviour that I disagree with, and doesn't enforce the behaviour that I prefer.


Slashes in regex expressions

# !! Use %r around regular expression.
'http://'.match =~ Regexp.new(/http:\/\//)
# 1 file inspected, no offenses detected
'http://'.match =~ Regexp.new(/http:/)

pros

regex is universal

  • you can take a regex from one language and (most of the time) it will work in another
  • AllowInnerSlashes forces you to escape characters, which is standard

cons

  • Have to type more characters
  • Escaping can become confusing

Extra space inside class/method bodies

class V1::IdentityAPI < Grape::API
  include ::NewRelic::Agent::MethodTracer

  module APIHelper
    helpers V1::Helpers
    helpers do
      def generate_response(identity, id, consumer)
      end
    end

  end
end

class V1::IdentityAPI < Grape::API
  include ::NewRelic::Agent::MethodTracer

  module APIHelper

    helpers V1::Helpers
    helpers do
      def generate_response(identity, id, consumer)
      end
    end

  end

end

pros

  • Only two more characters
  • Adds visibility to 'include' statements, constants etc.

cons

  • Adds more lines/space to classes

Unless vs. If

run_this_extra_method(variable: "thing") unless 'this' == 'that'

# or

run_this_extra_method(variable: "thing") if 'this' != 'that'

pros

  • Sounds more like regular English
  • Can be used with else

cons

  • Breaking from ruby style

Double vs. Single quotes

CONST = 'this is a constant string'
CLASS = "this is a #{self.class.name}"
MSG   = "This is a message that you're interested in"

Single quotes will automatically escape anything they can

 =>$ irb
2.4.1 :001 > 'tha\t\'s' # => "tha\\t's"
2.4.1 :002 > "tha\t's"  # => "tha\t's"

pros

  • Apostrophes are common in text
  • Interpolation is a common operation
  • More homogenous
  • Characters aren't escaped

cons

  • Characters aren't escaped

Don't force one-line if methods

The most important part of a conditional statement is the conditional.

  • it's often important to first know why something happened.
TheseThings.sort.select { |el| el.zero? } if i.zero?

# vs.

if i.zero?
  TheseThings.sort.select { |el| el.zero? }
end
  • One-line if statements are really useful when they're short.

_if...

  • the conditional is important, or
  • the line is long

then the regular form is more readable.


pros

  • Greater/quicker visibility over logic

cons

  • More LOC

Other mentions:

Don't force the guard clause

But you should force the guard clause! It stops horrible nesting and unreadable code. However there are still cases where this happens

def positive?(number)
  return true if number > 0
  false
end

# vs.

def negative?(number)
  if number < 0
    true
  else
    false
  end
end

The File

# Allow slashes inside regex expressions
Style/RegexpLiteral:
  AllowInnerSlashes: true

# Empty line at the beginning of class/module block
Layout/EmptyLinesAroundClassBody:
  EnforcedStyle: empty_lines
Layout/EmptyLinesAroundModuleBody:
  EnforcedStyle: empty_lines

# Unless adds an extra layer of abstraction to 'if not'
Style/NegatedIf:
  Enabled: false

# Use double quotes instead of single
Style/StringLiterals:
  EnforcedStyle: double_quotes

# Don't force the guard clause
Style/GuardClause:
  Enabled: false

# Don't force one-line if methods
Style/IfUnlessModifier:
  Enabled: false