Standard

Now we switch to standard gem https://github.com/testdouble/standard which provides better defaults than rubocop

Install with

gem "standard", "~> 1.0", require: false

and add

# .rubocop.yml
require: standard

inherit_gem:
  standard: config/base.yml

If you want to use todos https://evilmartians.com/chronicles/rubocoping-with-legacy-bring-your-ruby-code-up-to-standard

# .rubocop.yml
# We want Exclude directives from different
# config files to get merged, not overwritten
inherit_mode:
  merge:
    - Exclude

require:
  # Standard's config uses custom cops, # so it must be loaded
  - standard

inherit_gem:
  standard: config/base.yml
  # You can also choose a Ruby-version-specific config
  # standard: config/ruby-3.0.yml

inherit_from:
  - .rubocop_todo.yml
  - .rubocop_strict.yml
# Sometimes we enable metrics cops
# (which are disabled in Standard by default)
#
# Metrics:
#   Enabled: true

# Global options, like Ruby version
AllCops:
  SuggestExtensions: false
  TargetRubyVersion: 3.2

Enable in editors https://github.com/testdouble/standard#language-server-protocol-support

Rubocop

rubocop my-file.rb
# safe auto correct
rubocop -a
# auto correct all
rubocop -A
# auto correct only layout (formatting offenses)
rubocop -x
# only specific cops
rubocop --only Rails/Blank,Naming/FileName
# add rubocop comments that disable warnings and fix what can be fixes
rubocop --auto-correct --disable-uncorrectable

Cache is used by default AllCopps: UseCache is true and stored in ~/.cache/rubocop_cache/

Configuration

https://docs.rubocop.org/rubocop/configuration.html Default configuration https://github.com/rubocop-hq/rubocop/blob/master/config/default.yml

Configuration can inherit parent configuration and override (hash are merged or canceled with ~, other types are overriden.

# rubocop --auto-gen-config # generate .rubocop_todo.yml
inherit_from: .rubocop_todo.yml

Rails/HasAndBelongsToMany:
  Include:
    - app/models/*.rb
  Exclude:
    - app/models/problematic.rb

Layout/LineLength:
  Enabled: false

# info (still returns zero 0 value), refactor, convention, warning, error and fatal.
Lint:
  Severity: error

Extension

# .rubocop.yml
require:
  - ../my/file.rb
  - rubocop-extension

Create using https://github.com/rubocop-hq/rubocop-extension-generator

rubocop-extension-generator rubocop-dependent

Instructions https://docs.rubocop.org/rubocop/development.html

Note pattern https://github.com/rubocop-hq/rubocop-ast/blob/master/docs/modules/ROOT/pages/node_pattern.adoc

Example how rubocop-rails check if there is an unique index for that column name https://github.com/rubocop-hq/rubocop-rails/blob/master/lib/rubocop/cop/rails/unique_validation_without_index.rb#L61

CI

TODO: https://nvuillam.github.io/mega-linter/installation/ for github action

https://docs.rubocop.org/rubocop/automated_code_review.html for example pronto

My defaults

Do not use home ~/.rubocop.yml since it can be different for different projects (it is by default included if there is no local .rubocop.yml)

# http://blog.trk.in.rs/2021/02/06/rubocop/
# ~/.rubocop.yml is used when there is no local .rubocop.yml
AllCops:
  Exclude:
    - db/schema.rb
    - node_modules/**/*
    - db/migrate/*

# 'class ActionDispatch::IntegrationTest' in single line, no need two lines
Style/ClassAndModuleChildren:
  Enabled: false

# it is OK that code explains instead top-level class documentation comment
Style/Documentation:
  Enabled: false

# config, tasks and test for setup data could be very long
Metrics/BlockLength:
  Exclude:
    - 'lib/**/*'
    - 'test/**/*'
    - 'config/**/*'

# big test big ABC size
Metrics/AbcSize:
  Max: 25
  Exclude:
    - 'test/**/*'

# line length is not important in db and tests
Layout/LineLength:
  Max: 135
  Exclude:
    - 'db/**/*'
    - 'test/**/*'
    - 'spec/**/*'

# put comma after each line [1,]
Style/TrailingCommaInArrayLiteral:
  Enabled: false

# put comma after each line {a:1,}
Style/TrailingCommaInHashLiteral:
  Enabled: false

# also in arguments
Style/TrailingCommaInArguments:
  Enabled: false

# methods in 10 lines are OK but some are bigger
Metrics/MethodLength:
  Max: 15
  Exclude:
    - 'lib/**/*'
    - 'test/**/*'

# classes could be huge in tests
Metrics/ClassLength:
  Exclude:
    - 'test/**/*'

# do not need to write # frozen_string_literal: true
Style/FrozenStringLiteralComment:
  Enabled: false

# Rails:
#   Enabled: true

# Rails/FilePath:
#   Enabled: false

# errors.add(:base, 'Failed') and return false # no need to use &&
Style/AndOr:
  Enabled: false

# assert_match /regexp/, response.body # no need for parenthesis
Lint/AmbiguousRegexpLiteral:
  Enabled: false

# s = %q{Hi} # no need to use `%q` only for strings that contain both single quotes and double quotes
# Style/UnneededPercentQ:
# Style/RedudantPercentQ:
#   Enabled: false

# class Post < ActiveRecord::Base # no need to subclass `ApplicationRecord`
# Rails/ApplicationRecord:
#   Enabled: false

# $:.push File.expand_path('lib', __dir__) # no need to use $LOAD_PATH
Style/SpecialGlobalVars:
  Enabled: false

# in scripts I like to define methods at the end using BEGIN block
Style/BeginBlock:
  Enabled: false

# use refute_ instead of assert_not _ in minitest
# Rails/RefuteMethods:
#   Enabled: false

# port: (Rails.env.production? ? nil : Rails.env.development? ? Rack::Server.new.options[:Port] : 3333),
Style/NestedTernaryOperator:
  Enabled: false

Style/LambdaCall:
  Enabled: false
# method(*%i[a b])
# Lint/UnneededSplatExpansion:
# Lint/RedudantSplatExpansion:
#   Enabled: false

# new pending cops
Style/HashEachMethods:
  Enabled: true
Style/HashTransformKeys:
  Enabled: true
Style/HashTransformValues:
  Enabled: true

# use two spaces for indent
Layout/MultilineMethodCallIndentation:
  EnforcedStyle: indented

# Use attr_accessor in different places, near the related usage
Style/AccessorGrouping:
  Enabled: false