Skip to content

Instantly share code, notes, and snippets.

@glv
Last active August 25, 2019 16:49
Show Gist options
  • Save glv/c7a9c814d8cd9bec93faa2f2a43c1bb2 to your computer and use it in GitHub Desktop.
Save glv/c7a9c814d8cd9bec93faa2f2a43c1bb2 to your computer and use it in GitHub Desktop.
Rubocop configuration (draft)
# This is not a valid .rubocop.yml file. See gist comment for explanation.
Layout/AlignArray:
EnforcedHashRocketStyle: table
EnforcedColonStyle: table
# Ruby is an expression language. Continued lines should be aligned with the
# expression they're part of, not the beginning of the line they happened to
# start on.
Layout/BlockAlignment:
EnforcedStyleAlignWith: start_of_block
Layout/EmptyLines: false?
Layout/EmptyLinesAroundClassBody:
EnforcedStyle: empty_lines_except_namespace
Layout/EmptyLinesAroundModuleBody:
EnforcedStyle: empty_lines_except_namespace
Layout/EndOfLine:
EnforcedStyle: lf
Layout/FirstParameterIndentation:
EnforcedStyle: consistent_relative_to_receiver # Ruby is an expression language. See above.
Layout/SpaceAroundEqualsInParameterDefault:
EnforcedStyle: no_space # bind them tightly to make individual parameters easy to see
Layout/SpaceBeforeBlockBraces:
EnforcedStyle: no_space # bind tightly for concision.
Layout/SpaceInsideBlockBraces:
SpaceBeforeBlockParameters: false # bind tightly for concision. `{|` should read as a single token
Layout/SpaceInsideHashLiteralBraces:
EnforcedStyle: no_space # for consistency with SpaceInsideArrayLiteralBrackets
Style/BarePercentLiterals:
EnforcedStyle: percent_q # explicit is better
Style/BlockDelimiters:
EnforcedStyle: semantic # Jim was right
Style/BracesAroundHashParameters:
EnforcedStyle: context_dependent
# The default here is based on the mistaken notion that this operator should
# be called "case equality" (i.e., that it's somehow just a private tool for
# case statements). But the operator is actually Ruby's generalized "matches"
# operator, and if read that way, using it explicitly is perfectly fine.
Style/CaseEquality: false
Style/ClassAndModuleChildren:
EnforcedStyle: compact
Style/CommandLiteral:
EnforcedStyle: percent_x
# This is rare (currently only two occurrences in our codebase) but
# occasionally useful because aligning complex conditions can highlight their
# parallel structure and minor differences.
Style/EmptyCaseCondition: false
# Sometimes you want to highlight what you're doing, sometimes you want to
# highlight that it's conditional. If you want to highlight what you're
# doing, shoving the conditional off toward the right margin makes perfect
# sense.
Style/IfUnlessModifier: false
# Maybe don't need this with BlockDelimiters: semantic?
Style/MethodCalledOnDoEndBlock: true
# Since we usually put the conditions at the end of a line rather than the
# beginning of the next line, parens are a signal toward the left side of the
# line that the condition is continued. That's important, especially with if
# statements --- the three-character indent for the continued condition is so
# close to the two-character indent of the body that it's easy to think the
# second condition line is actually the first line of the body. The paren is
# a visible signal that it's a multiline condition, *and* it forces the other
# condition lines to be indented by 4 spaces instead of three.
Style/ParenthesesAroundCondition:
AllowInMultilineConditions: true
# Braces are used for %q and %r constructs, consistent with most of our
# codebase (and also #{} constructs in string interpolation) and because
# unbalanced braces are uncommon in regular expressions. %w and %i use []
# because they produce arrays. %x uses () to suggest a function call. (But
# maybe just turn this cop completely off, because it should be permissible
# to change the delimeters if the values they delimit need to use those same
# characters, to avoid the need for escaping.)
Style/PercentLiteralDelimiters:
PreferredDelimiters:
default: "{}"
"%w": "[]"
"%W": "[]"
"%i": "[]"
"%I": "[]"
"%x": "()"
# A note about Style/RedundantSelf. The docs say this:
#
# > The usage of self is only needed when:
# >
# > * Sending a message to same object with zero arguments in presence of a
# > method name clash with an argument or a local variable.
# > * Calling an attribute writer to prevent an local variable assignment.
#
# But there is one other case: when you're calling a method on self that is
# named after a Ruby keyword (typically `class`).
@glv
Copy link
Author

glv commented Aug 15, 2019

Our team doesn't use Rubocop regularly (for both good and bad reasons). So this isn't, so far as I know, a valid Rubocop config file, and it certainly doesn't reflect decisions that a team has agreed upon together. And I got sidetracked on other things before I finished it.

But last year I started down the path of introducing it, and began preparing this file. And I've always believed that deviations from "the community norm" should be driven by a rationale stronger than "I like this better". So I commented almost everything with an explanation of why I thought it was the right choice, both to clarify my thinking and to prepare for talking to my team about why I was proposing this as a starting point for discussion.

I'm happy to discuss/explain/argue these preferences, within reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment