# In general, we should care more about consistency and avoidance of # bike-shedding than any specific aesthetic choice on code quality. # # However, in some cases, the default Rubocop rules merit changing where their # defaults don't optimally live up to some additional values: # # 1. Correctness # # If a certain style will generally result in fewer errors, it should be # preferred. E.g.: using attr_readers instead of @ivars will produce # noticeable exceptions vs un-noticed nils; prefixed access modifiers to # method definitions prevent accidental scope changes as methods are moved. # # 2. Focused diffs # # Trailing commas, aligning relative to indentation level (params, # conditional assignment, etc), minimising whitespace changes, "flat" module # namespacing, all produce less whitespace noise in diffs as they change and # evolve. # # 3. Code clarity # # Access modifier prefixes and allowing for some flexibility in formatting # numbers improve the ability to communicate intent and context in code. # Likewise, choosing whether to use guard clauses or conditionals is a # matter of readability that a developer can judge better than a linter. # # 4. Pragmatism # # Formatting code for easy paste-ability into IRB/Pry is a good example of # this. # # 5. Appropriate subjectivity # # Certain choices are best made by a human code reviewer, not a linter. # While consistency is important, it can sometimes be in conflict with # clarity or other team values. AllCops: TargetRubyVersion: ~ ExtraDetails: true Metrics/AbcSize: Enabled: false # Disable code "length" metrics other than line length, as they are somewhat # subjective and not directly great measures of code complexity (though are # often pretty decent trailing indicators) Metrics/ModuleLength: Enabled: false Metrics/ClassLength: Enabled: false Metrics/BlockLength: Enabled: false Metrics/MethodLength: Enabled: false # Discourage methods with many _unnamed_ arguments (as parameter ordering can # be confusing), but allow many named arguments. Metrics/ParameterLists: CountKeywordArgs: false Bundler/OrderedGems: Enabled: false Layout/DefEndAlignment: AutoCorrect: true # An explicit return (e.g. deep within conditionals) can be both clearer and # more resilient to bugs from refactoring, where the return is no longer in # tail position of the method. Style/RedundantReturn: Enabled: false Style/EmptyMethod: Enabled: false # Use trailing method dots, because it maximises paste-ability into REPLs Layout/DotPosition: EnforcedStyle: trailing Layout/MultilineMethodCallIndentation: EnforcedStyle: indented Layout/FirstHashElementIndentation: EnforcedStyle: consistent Layout/FirstArrayElementIndentation: EnforcedStyle: consistent # Prefer: # # some_method 'foo', # 'bar', # 'baz' # # over: # # # some_method 'foo', # 'bar', # 'baz' # # because renaming a method reduce irrelevant indentation changes. # # Generally, put positional arguments on the first line, and kwargs on # subsequent lines, but this isn't universally the best choice. # # Better yet, if parameters must be spread over multiple lines, prefer the # following (for which there is not a rule): # # some_method( # 'foo', # 'bar', # 'baz', # ) # Layout/ParameterAlignment: EnforcedStyle: with_fixed_indentation # Encourage trailing commas on multi-line lists to allow easy re-ordering and # clearer diffs on changes. Style/TrailingCommaInArrayLiteral: EnforcedStyleForMultiline: consistent_comma Style/TrailingCommaInHashLiteral: EnforcedStyleForMultiline: consistent_comma # This cop does not work consistently and often interprets non-multi-line calls # as multi-line adding commas where it shouldn't! Since argument lists are # generally fixed length and rarely re-ordered, the arguments above for # hash/array literal commas is not as strong and we will instead never have # trailing commas in method calls. Style/TrailingCommaInArguments: EnforcedStyleForMultiline: no_comma # The "new_line" style for this is close to what we want, but it behaves poorly # in cases where an argument is an array or hash and is spread across multiple # lines. Layout/MultilineMethodCallBraceLayout: Enabled: false # Rewrite long lines Layout/LineLength: Enabled: true AutoCorrect: true # In-lining access modifiers removes risk of accidentally changing access level # when re-ordering methods and improves clarity about method access Style/AccessModifierDeclarations: EnforcedStyle: inline # It is better to have deterministic booleans in some cases, and `!!` is the # most precise way to coerce truthy values (`!x.nil?` is NOT the same thing). Style/DoubleNegation: Enabled: false # Prefer: # # foo = # if foo? # bar # else # baz # end # # over alternatives, as it offers the right balance between: consistent # indentation, minimising unnecessary diff churn (e.g. when renaming the # variable), and shorter line length. Layout/MultilineAssignmentLayout: Enabled: true Layout/EndAlignment: EnforcedStyleAlignWith: variable Lint/AmbiguousBlockAssociation: Exclude: # Describe blocks in particular can be quite large - '**/*_spec.rb' # Well-named classes are more important than documentation Style/Documentation: Enabled: false Style/BlockDelimiters: AutoCorrect: false # Best caught in code review EnforcedStyle: semantic BracesRequiredMethods: ['sig'] # Sorbet IgnoredMethods: ['expect', 'let', 'let!', 'subject', 'it', 'fit', 'xit', 'before', 'after'] Exclude: - '**/*_spec.rb' # Prefer namespaced class definitions on single line to: # # 1. allow renaming/re-organizing namespaces without superfluous diffs full of # whitespace changes; # 3. have consistent consant lookup, relative to self or top-level Style/ClassAndModuleChildren: EnforcedStyle: compact # Don't autocorrect to allow alternative underscoring, # ie 2017_12_25 Style/NumericLiterals: Enabled: true AutoCorrect: false # Leave it to the coder to make this decision Style/GuardClause: Enabled: false # Default style prefers usage of a global function (Kernel#format). % is "ugly" # and a named method would be preferred, but not over a global which may be # overridden in the current class or not available (e.g. in BasicObject) Style/FormatString: EnforcedStyle: 'percent' # Disable this performance optimization - it can make the code less clear, and # the =~ operator introduces global variables #Performance/RedundantMatch: # Enabled: false # We have several comments discussing unicode normalization. This rule doesn't # particularly seem useful for code quality or team practices, so disabling. Style/AsciiComments: Enabled: false # An explicit self can provide clarity in some situations, even if technically # redundant. Appropriate usage of self is better caught in code review by # peers. Style/RedundantSelf: Enabled: false # A specialized exception class will take one or more arguments and construct # the message from it. Both variants make sense. Style/RaiseArgs: Enabled: false # Consistency is best, so since we definitely need double quotes often, let's # just use them everywhere. Style/StringLiterals: EnforcedStyle: 'double_quotes' # This feels subjective and best left to code review to determine what is # suitable on a case by case basis. Style/EmptyCaseCondition: Enabled: false # Just because you _can_ fix a conditional on the same line, doesn't mean you # should. Postfix conditionals are great for guards and other simple cases, # but in other cases this can obscure intent. Style/IfUnlessModifier: Enabled: false # This doesn't take into account sorbet typed: comments Layout/EmptyLineAfterMagicComment: Enabled: false Layout/SpaceInsideHashLiteralBraces: EnforcedStyle: no_space EnforcedStyleForEmptyBraces: no_space Style/FrozenStringLiteralComment: AutoCorrect: true Enabled: false # Ideally we'd have a rule here with more options as this is not perfect # either, but this is added to prevent situations such as: # # validate :email, # presence: true, # email: true # # Instead: # # validate :email, # presence: true, # email: true # # But ideally: # # validate :email, { # presence: true, # email: true # } Layout/ArgumentAlignment: EnforcedStyle: with_fixed_indentation