From ffeb9fbdc9003f0d125573d2fbb9079df50228c7 Mon Sep 17 00:00:00 2001 From: Issy Long Date: Wed, 26 Oct 2022 15:30:43 +0000 Subject: [PATCH] STYLEGUIDE: For each styleguide recommendation, link to the RuboCop rule - This allows people who are reading the style guide to investigate the configuration of the RuboCop rules in their apps if they wish, without having to Google the words in our styleguide which might not match the RuboCop rule explanation, and guess as to what the cop is called. Co-authored-by: Issy Long Co-authored-by: Elena Tanasoiu --- STYLEGUIDE.md | 66 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md index 1e55a3b..476fcc0 100644 --- a/STYLEGUIDE.md +++ b/STYLEGUIDE.md @@ -34,9 +34,11 @@ This is GitHub's Ruby Style Guide, inspired by [RuboCop's guide][rubocop-guide]. * Use soft-tabs with a two space indent. [[link](#default-indentation)] + * RuboCop rule: Layout/IndentationStyle * Indent `when` with the start of the `case` expression. [[link](#indent-when-as-start-of-case)] + * RuboCop rule: Layout/CaseIndentation ``` ruby # bad @@ -80,10 +82,18 @@ end * Never leave trailing whitespace. [[link](#trailing-whitespace)] + * RuboCop rule: Layout/TrailingWhitespace * Use spaces around operators, after commas, colons and semicolons, around `{` and before `}`. [[link](#spaces-operators)] + * RuboCop rule: Layout/SpaceAroundOperators + * RuboCop rule: Layout/SpaceAfterComma + * RuboCop rule: Layout/SpaceAfterColon + * RuboCop rule: Layout/SpaceBeforeBlockBraces + * RuboCop rule: Layout/SpaceInsideHashLiteralBraces + * RuboCop rule: Style/HashSyntax + * RuboCop rule: Layout/SpaceAroundOperators ``` ruby sum = 1 + 2 @@ -94,6 +104,8 @@ a, b = 1, 2 * No spaces after `(`, `[` or before `]`, `)`. [[link](#no-spaces-braces)] + * RuboCop rule: Layout/SpaceInsideParens + * RuboCop rule: Layout/SpaceInsideReferenceBrackets ``` ruby some(arg).other @@ -102,6 +114,7 @@ some(arg).other * No spaces after `!`. [[link](#no-spaces-bang)] + * RuboCop rule: Layout/SpaceAfterNot ``` ruby !array.include?(element) @@ -111,10 +124,12 @@ some(arg).other * End each file with a [newline](https://github.com/bbatsov/ruby-style-guide#newline-eof). [[link](#newline-eof)] + * RuboCop rule: Layout/TrailingEmptyLines * Use empty lines between `def`s and to break up a method into logical paragraphs. [[link](#empty-lines-def)] + * RuboCop rule: Layout/EmptyLineBetweenDefs ``` ruby def some_method @@ -134,12 +149,14 @@ end * Keep each line of code to a readable length. Unless you have a reason to, keep lines to a maximum of 118 characters. Why 118? That's the width at which the pull request diff UI needs horizontal scrolling (making pull requests harder to review). [[link](#line-length)] + * RuboCop rule: Layout/LineLength ## Classes * Avoid the usage of class (`@@`) variables due to their unusual behavior in inheritance. [[link](#class-variables)] + * RuboCop rule: Style/ClassVars ``` ruby class Parent @@ -164,6 +181,7 @@ Parent.print_class_var # => will print "child" * Use `def self.method` to define singleton methods. This makes the methods more resistant to refactoring changes. [[link](#singleton-methods)] + * RuboCop rule: Style/ClassMethodsDefinitions ``` ruby class TestClass @@ -181,6 +199,7 @@ class TestClass * Avoid `class << self` except when necessary, e.g. single accessors and aliased attributes. [[link](#class-method-definitions)] + * RuboCop rule: Style/ClassMethodsDefinitions ``` ruby class TestClass @@ -214,6 +233,8 @@ end * Indent the `public`, `protected`, and `private` methods as much the method definitions they apply to. Leave one blank line above them. [[link](#access-modifier-identation)] + * RuboCop rule: Layout/AccessModifierIndentation + * RuboCop rule: Layout/EmptyLinesAroundAccessModifier ``` ruby class SomeClass @@ -231,6 +252,7 @@ end * Avoid explicit use of `self` as the recipient of internal class or instance messages unless to specify a method shadowed by a variable. [[link](#self-messages)] + * RuboCop rule: Style/RedundantSelf ``` ruby class SomeClass @@ -248,6 +270,7 @@ end * Prefer `%w` to the literal array syntax when you need an array of strings. [[link](#percent-w)] + * RuboCop rule: Style/WordArray ``` ruby # bad @@ -265,6 +288,7 @@ STATES = %w(draft open closed) * Use symbols instead of strings as hash keys. [[link](#symbols-as-keys)] + * RuboCop rule: Style/StringHashKeys ``` ruby # bad @@ -300,9 +324,10 @@ end Avoid calling `send` and its cousins unless you really need it. Metaprogramming can be extremely powerful, but in most cases you can write code that captures your meaning by being explicit: [[link](#avoid-send)] + * RuboCop rule: Style/Send ``` ruby -# avoid +# avoid unless [:base, :head].include?(base_or_head) raise ArgumentError, "base_or_head must be either :base or :head" end @@ -366,6 +391,7 @@ end Use the Ruby 1.9 syntax for hash literals when all the keys are symbols: [[link](#symbols-as-hash-keys)] +* RuboCop rule: Style/StringHashKeys ``` ruby # bad @@ -396,6 +422,7 @@ link_to("Account", controller: "users", action: "show", id: user) If you have a hash with mixed key types, use the legacy hashrocket style to avoid mixing styles within the same hash: [[link](#consistent-hash-syntax)] +* RuboCop rule: Style/HashSyntax ``` ruby @@ -417,6 +444,7 @@ hsh = { [Keyword arguments](http://magazine.rubyist.net/?Ruby200SpecialEn-kwarg) are recommended but not required when a method's arguments may otherwise be opaque or non-obvious when called. Additionally, prefer them over the old "Hash as pseudo-named args" style from pre-2.0 ruby. [[link](#keyword-arguments)] +* RuboCop rule: Style/OptionalBooleanParameter So instead of this: @@ -444,21 +472,26 @@ remove_member(user, skip_membership_check: true) * Use `snake_case` for methods and variables. [[link](#snake-case-methods-vars)] + * RuboCop rule: Naming/SnakeCase + * RuboCop rule: Naming/VariableName * Use `CamelCase` for classes and modules. (Keep acronyms like HTTP, RFC, XML uppercase.) [[link](#camelcase-classes-modules)] + * RuboCop rule: Naming/ClassAndModuleCamelCase * Use `SCREAMING_SNAKE_CASE` for other constants. [[link](#screaming-snake-case-constants)] + * RuboCop rule: Naming/ConstantName * The names of predicate methods (methods that return a boolean value) should end in a question mark. (i.e. `Array#empty?`). [[link](#bool-methods-qmark)] + * RuboCop rule: Naming/PredicateName * The names of potentially "dangerous" methods (i.e. methods that modify `self` or the arguments, `exit!`, etc.) should end with an exclamation mark. Bang methods - should only exist if a non-bang counterpart (method name which does NOT end with !) + should only exist if a non-bang counterpart (method name which does NOT end with !) also exists. [[link](#dangerous-method-bang)] @@ -466,6 +499,7 @@ remove_member(user, skip_membership_check: true) * Use `%w` freely. [[link](#use-percent-w-freely)] + * RuboCop rule: Style/WordArray ``` ruby STATES = %w(draft open closed) @@ -474,6 +508,7 @@ STATES = %w(draft open closed) * Use `%()` for single-line strings which require both interpolation and embedded double-quotes. For multi-line strings, prefer heredocs. [[link](#percent-parens-single-line)] + * RuboCop rule: Style/BarePercentLiterals ``` ruby # bad (no interpolation needed) @@ -494,6 +529,7 @@ STATES = %w(draft open closed) * Use `%r` only for regular expressions matching *more than* one '/' character. [[link](#percent-r-regular-expressions)] + * RuboCop rule: Style/RegexpLiteral ``` ruby # bad @@ -512,7 +548,7 @@ STATES = %w(draft open closed) * Avoid using $1-9 as it can be hard to track what they contain. Named groups can be used instead. [[link](#capture-with-named-groups)] - + * RuboCop rule: Lint/MixedRegexpCaptureTypes ``` ruby # bad /(regexp)/ =~ string @@ -571,6 +607,7 @@ documentation about the libraries that the current file uses. * Prefer string interpolation instead of string concatenation: [[link](#string-interpolation)] + * RuboCop rule: Style/StringConcatenation ``` ruby # bad @@ -584,6 +621,7 @@ email_with_name = "#{user.name} <#{user.email}>" will always work without a delimiter change, and `'` is a lot more common than `"` in string literals. [[link](#double-quotes)] + * RuboCop rule: Style/StringLiterals ``` ruby # bad @@ -615,6 +653,7 @@ end * Use `def` with parentheses when there are arguments. Omit the parentheses when the method doesn't accept any arguments. [[link](#method-parens-when-arguments)] + * RuboCop rule: Style/DefWithParentheses ``` ruby def some_method @@ -632,9 +671,11 @@ end always use parentheses in the method invocation. For example, write `f((3 + 2) + 1)`. [[link](#parens-no-spaces)] + * RuboCop rule: Style/MethodCallWithArgsParentheses * Never put a space between a method name and the opening parenthesis. [[link](#no-spaces-method-parens)] + * RuboCop rule: Style/ParenthesesAsGroupedExpression ``` ruby # bad @@ -650,6 +691,7 @@ f(3 + 2) + 1 * Never use `then` for multi-line `if/unless`. [[link](#no-then-for-multi-line-if-unless)] + * RuboCop rule: Style/MultilineIfThen ``` ruby # bad @@ -665,10 +707,12 @@ end * The `and` and `or` keywords are banned. It's just not worth it. Always use `&&` and `||` instead. [[link](#no-and-or-or)] + * RuboCop rule: Style/AndOr * Favor modifier `if/unless` usage when you have a single-line body. [[link](#favor-modifier-if-unless)] + * RuboCop rule: Style/MultilineTernaryOperator ``` ruby # bad @@ -682,6 +726,7 @@ do_something if some_condition * Never use `unless` with `else`. Rewrite these with the positive case first. [[link](#no-else-with-unless)] + * RuboCop rule: Style/UnlessElse ``` ruby # bad @@ -701,6 +746,7 @@ end * Don't use parentheses around the condition of an `if/unless/while`. [[link](#no-parens-if-unless-while)] + * RuboCop rule: Style/ParenthesesAroundCondition ``` ruby # bad @@ -720,6 +766,7 @@ end trivial. However, do use the ternary operator(`?:`) over `if/then/else/end` constructs for single line conditionals. [[link](#trivial-ternary)] + * RuboCop rule: Style/MultilineTernaryOperator ``` ruby # bad @@ -731,11 +778,13 @@ result = some_condition ? something : something_else * Avoid multi-line `?:` (the ternary operator), use `if/unless` instead. [[link](#no-multiline-ternary)] + * RuboCop rule: Style/MultilineTernaryOperator * Use one expression per branch in a ternary operator. This also means that ternary operators must not be nested. Prefer `if/else` constructs in these cases. [[link](#one-expression-per-branch)] + * RuboCop rule: Style/NestedTernaryOperator ``` ruby # bad @@ -757,6 +806,7 @@ end doesn't introduce a new scope (unlike `each`) and variables defined in its block will be visible outside it. [[link](#avoid-for)] + * RuboCop rule: Style/For ``` ruby arr = [1, 2, 3] @@ -776,6 +826,7 @@ arr.each { |elem| puts elem } definitions" (e.g. in Rakefiles and certain DSLs). Avoid `do...end` when chaining. [[link](#squiggly-braces)] + * RuboCop rule: Style/BlockDelimiters ``` ruby names = ["Bozhidar", "Steve", "Sarah"] @@ -798,11 +849,12 @@ end.map { |name| name.upcase } ``` * Some will argue that multiline chaining would look OK with the use of `{...}`, - but they should ask themselves: is this code really readable and can't the block's + but they should ask themselves: is this code really readable and can't the block's contents be extracted into nifty methods? * Avoid `return` where not required. [[link](#avoid-return)] + * RuboCop rule: Style/RedundantReturn ``` ruby # bad @@ -818,6 +870,7 @@ end * Use spaces around the `=` operator when assigning default values to method parameters: [[link](#spaces-around-equals)] + * RuboCop rule: Style/SpaceAroundEqualsInParameterDefault ``` ruby # bad @@ -850,6 +903,7 @@ if (v = next_value) == "hello" ... * Use `||=` freely to initialize variables. [[link](#memoize-away)] + * RuboCop rule: Style/OrAssignment ``` ruby # set name to Bozhidar, only if it's nil or false @@ -859,6 +913,7 @@ name ||= "Bozhidar" * Don't use `||=` to initialize boolean variables. (Consider what would happen if the current value happened to be `false`.) [[link](#no-memoization-for-boolean)] + * RuboCop rule: Style/OrAssignment ``` ruby # bad - would set enabled to true even if it was false @@ -873,9 +928,11 @@ enabled = true if enabled.nil? one-liner scripts is discouraged. Prefer long form versions such as `$PROGRAM_NAME`. [[link](#no-cryptic-vars)] + * RuboCop rule: Style/SpecialGlobalVars * Use `_` for unused block parameters. [[link](#underscore-unused-vars)] + * RuboCop rule: Style/UnusedBlockArgument ``` ruby # bad @@ -890,6 +947,7 @@ result = hash.map { |_, v| v + 1 } For example, `String === "hi"` is true and `"hi" === String` is false. Instead, use `is_a?` or `kind_of?` if you must. [[link](#type-checking-is-a-kind-of)] + * RuboCop rule: Style/CaseEquality Refactoring is even better. It's worth looking hard at any code that explicitly checks types.