STYLEGUIDE.md in rubocop-github-0.18.0 vs STYLEGUIDE.md in rubocop-github-0.19.0

- old
+ new

@@ -1,39 +1,44 @@ # Ruby Style Guide -* Use soft-tabs with a two space indent. +This is GitHub's Ruby Style Guide, inspired by [RuboCop's guide][rubocop-guide]. -* 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). +## Table of Contents +1. [Layout](#layout) + 1. [Indentation](#indentation) + 2. [Inline](#inline) + 3. [Newlines](#newlines) +2. [Maximum Line Length](#line-length) +3. [Classes](#classes) +4. [Collections](#collections) +5. [Documentation](#documentation) +6. [Dynamic Dispatch](#dynamic-dispatch) +7. [Exceptions](#exceptions) +8. [Hashes](#hashes) +9. [Keyword Arguments](#keyword-arguments) +10. [Naming](#naming) +11. [Percent Literals](#percent-literals) +12. [Regular Expressions](#regular-expressions) +13. [Requires](#requires) +14. [Strings](#strings) +15. [Methods](#methods) + 1. [Method definitions](#method-definitions) + 2. [Method calls](#method-calls) +16. [Conditional Expressions](#conditional-expressions) + 1. [Conditional keywords](#conditional-keywords) + 2. [Ternary operator](#ternary-operator) +17. [Syntax](#syntax) -* Never leave trailing whitespace. +## Layout -* End each file with a [newline](https://github.com/bbatsov/ruby-style-guide#newline-eof). +### Indentation -* Use spaces around operators, after commas, colons and semicolons, around `{` - and before `}`. +* Use soft-tabs with a two space indent. + <a name="default-indentation"></a><sup>[[link](#default-indentation)]</sup> -``` ruby -sum = 1 + 2 -a, b = 1, 2 -1 > 2 ? true : false; puts "Hi" -[1, 2, 3].each { |e| puts e } -``` - -* No spaces after `(`, `[` or before `]`, `)`. - -``` ruby -some(arg).other -[1, 2, 3].length -``` - -* No spaces after `!`. - -``` ruby -!array.include?(element) -``` - * Indent `when` with the start of the `case` expression. + <a name="indent-when-as-start-of-case"></a><sup>[[link](#indent-when-as-start-of-case)]</sup> ``` ruby # bad message = case when song.name == "Misty" @@ -69,12 +74,49 @@ else song.play end ``` +### Inline + +* Never leave trailing whitespace. + <a name="trailing-whitespace"></a><sup>[[link](#trailing-whitespace)]</sup> + +* Use spaces around operators, after commas, colons and semicolons, around `{` + and before `}`. + <a name="spaces-operators"></a><sup>[[link](#spaces-operators)]</sup> + +``` ruby +sum = 1 + 2 +a, b = 1, 2 +1 > 2 ? true : false; puts "Hi" +[1, 2, 3].each { |e| puts e } +``` + +* No spaces after `(`, `[` or before `]`, `)`. + <a name="no-spaces-braces"></a><sup>[[link](#no-spaces-braces)]</sup> + +``` ruby +some(arg).other +[1, 2, 3].length +``` + +* No spaces after `!`. + <a name="no-spaces-bang"></a><sup>[[link](#no-spaces-bang)]</sup> + +``` ruby +!array.include?(element) +``` + +### Newlines + +* End each file with a [newline](https://github.com/bbatsov/ruby-style-guide#newline-eof). + <a name="newline-eof"></a><sup>[[link](#newline-eof)]</sup> + * Use empty lines between `def`s and to break up a method into logical paragraphs. + <a name="empty-lines-def"></a><sup>[[link](#empty-lines-def)]</sup> ``` ruby def some_method data = initialize(options) @@ -86,14 +128,20 @@ def some_method result end ``` +## Maximum Line Length + +* 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). + <a name="line-length"></a><sup>[[link](#line-length)]</sup> + ## Classes * Avoid the usage of class (`@@`) variables due to their unusual behavior in inheritance. + <a name="class-variables"></a><sup>[[link](#class-variables)]</sup> ``` ruby class Parent @@class_var = "parent" @@ -113,10 +161,11 @@ class variable. Class instance variables should usually be preferred over class variables. * Use `def self.method` to define singleton methods. This makes the methods more resistant to refactoring changes. + <a name="singleton-methods"></a><sup>[[link](#singleton-methods)]</sup> ``` ruby class TestClass # bad def TestClass.some_method @@ -129,10 +178,11 @@ end ``` * Avoid `class << self` except when necessary, e.g. single accessors and aliased attributes. + <a name="class-method-definitions"></a><sup>[[link](#class-method-definitions)]</sup> ``` ruby class TestClass # bad class << self @@ -161,10 +211,11 @@ end ``` * Indent the `public`, `protected`, and `private` methods as much the method definitions they apply to. Leave one blank line above them. + <a name="access-modifier-identation"></a><sup>[[link](#access-modifier-identation)]</sup> ``` ruby class SomeClass def public_method # ... @@ -177,10 +228,11 @@ end ``` * Avoid explicit use of `self` as the recipient of internal class or instance messages unless to specify a method shadowed by a variable. + <a name="self-messages"></a><sup>[[link](#self-messages)]</sup> ``` ruby class SomeClass attr_accessor :message @@ -193,10 +245,11 @@ ## Collections * Prefer `%w` to the literal array syntax when you need an array of strings. + <a name="percent-w"></a><sup>[[link](#percent-w)]</sup> ``` ruby # bad STATES = ["draft", "open", "closed"] @@ -206,12 +259,14 @@ * Use `Set` instead of `Array` when dealing with unique elements. `Set` implements a collection of unordered values with no duplicates. This is a hybrid of `Array`'s intuitive inter-operation facilities and `Hash`'s fast lookup. + <a name="prefer-set"></a><sup>[[link](#prefer-set)]</sup> * Use symbols instead of strings as hash keys. + <a name="symbols-as-keys"></a><sup>[[link](#symbols-as-keys)]</sup> ``` ruby # bad hash = { "one" => 1, "two" => 2, "three" => 3 } @@ -220,10 +275,11 @@ ``` ## Documentation Use [TomDoc](http://tomdoc.org) to the best of your ability. It's pretty sweet: +<a name="tomdoc"></a><sup>[[link](#tomdoc)]</sup> ``` ruby # Public: Duplicate some text an arbitrary number of times. # # text - The String to be duplicated. @@ -241,10 +297,11 @@ ``` ## Dynamic Dispatch 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: +<a name="avoid-send"></a><sup>[[link](#avoid-send)]</sup> ``` ruby # avoid unless [:base, :head].include?(base_or_head) raise ArgumentError, "base_or_head must be either :base or :head" @@ -266,10 +323,11 @@ end ``` ## Exceptions * Don't use exceptions for flow of control. + <a name="exceptions-flow-control"></a><sup>[[link](#exceptions-flow-control)]</sup> ``` ruby # bad begin n / d @@ -284,10 +342,11 @@ n / d end ``` * Rescue specific exceptions, not `StandardError` or its superclasses. + <a name="specific-exceptions"></a><sup>[[link](#specific-exceptions)]</sup> ``` ruby # bad begin # an exception occurs here @@ -304,10 +363,11 @@ ``` ## Hashes Use the Ruby 1.9 syntax for hash literals when all the keys are symbols: +<a name="symbols-as-hash-keys"></a><sup>[[link](#symbols-as-hash-keys)]</sup> ``` ruby # bad user = { :login => "defunkt", @@ -320,10 +380,11 @@ name: "Chris Wanstrath" } ``` Use the 1.9 syntax when calling a method with Hash options arguments or named arguments: +<a name="symbols-as-hash-method-arguments"></a><sup>[[link](#symbols-as-hash-method-arguments)]</sup> ``` ruby # bad user = User.create(:login => "jane") link_to("Account", :controller => "users", :action => "show", :id => user) @@ -332,12 +393,15 @@ user = User.create(login: "jane") 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: +<a name="consistent-hash-syntax"></a><sup>[[link](#consistent-hash-syntax)]</sup> ``` ruby + +``` ruby # bad hsh = { user_id: 55, "followers-count" => 1000 } @@ -350,22 +414,25 @@ ``` ## Keyword Arguments [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. +<a name="keyword-arguments"></a><sup>[[link](#keyword-arguments)]</sup> So instead of this: + ``` ruby def remove_member(user, skip_membership_check=false) # ... end # Elsewhere: what does true mean here? remove_member(user, true) ``` -Do this, which is much clearer. +Do this, which is much clearer: + ``` ruby def remove_member(user, skip_membership_check: false) # ... end @@ -374,34 +441,41 @@ ``` ## Naming * Use `snake_case` for methods and variables. + <a name="snake-case-methods-vars"></a><sup>[[link](#snake-case-methods-vars)]</sup> * Use `CamelCase` for classes and modules. (Keep acronyms like HTTP, RFC, XML uppercase.) + <a name="camelcase-classes-modules"></a><sup>[[link](#camelcase-classes-modules)]</sup> * Use `SCREAMING_SNAKE_CASE` for other constants. + <a name="screaming-snake-case-constants"></a><sup>[[link](#screaming-snake-case-constants)]</sup> * The names of predicate methods (methods that return a boolean value) should end in a question mark. (i.e. `Array#empty?`). + <a name="bool-methods-qmark"></a><sup>[[link](#bool-methods-qmark)]</sup> * 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 !) also exists. + <a name="dangerous-method-bang"></a><sup>[[link](#dangerous-method-bang)]</sup> ## Percent Literals * Use `%w` freely. + <a name="use-percent-w-freely"></a><sup>[[link](#use-percent-w-freely)]</sup> ``` ruby STATES = %w(draft open closed) ``` * Use `%()` for single-line strings which require both interpolation and embedded double-quotes. For multi-line strings, prefer heredocs. + <a name="percent-parens-single-line"></a><sup>[[link](#percent-parens-single-line)]</sup> ``` ruby # bad (no interpolation needed) %(<div class="text">Some text</div>) # should be "<div class=\"text\">Some text</div>" @@ -417,10 +491,11 @@ # good (requires interpolation, has quotes, single line) %(<tr><td class="name">#{name}</td>) ``` * Use `%r` only for regular expressions matching *more than* one '/' character. + <a name="percent-r-regular-expressions"></a><sup>[[link](#percent-r-regular-expressions)]</sup> ``` ruby # bad %r(\s+) @@ -434,10 +509,11 @@ ## Regular Expressions * Avoid using $1-9 as it can be hard to track what they contain. Named groups can be used instead. + <a name="capture-with-named-groups"></a><sup>[[link](#capture-with-named-groups)]</sup> ``` ruby # bad /(regexp)/ =~ string ... @@ -449,19 +525,21 @@ process meaningful_var ``` * Be careful with `^` and `$` as they match start/end of line, not string endings. If you want to match the whole string use: `\A` and `\z`. + <a name="regex-begin-end-markers"></a><sup>[[link](#regex-begin-end-markers)]</sup> ``` ruby string = "some injection\nusername" string[/^username$/] # matches string[/\Ausername\z/] # don't match ``` * Use `x` modifier for complex regexps. This makes them more readable and you can add some useful comments. Just be careful as spaces are ignored. + <a name="x-modifier-complex-regex"></a><sup>[[link](#x-modifier-complex-regex)]</sup> ``` ruby regexp = %r{ start # some text \s # white space char @@ -474,10 +552,11 @@ ## Requires Always `require` dependencies used directly in a script at the start of the same file. Resources that will get autoloaded on first use—such as Rails models, controllers, or helpers—don't need to be required. +<a name="require-dependencies-directly"></a><sup>[[link](#require-dependencies-directly)]</sup> ``` ruby require "set" require "time" @@ -489,10 +568,11 @@ documentation about the libraries that the current file uses. ## Strings * Prefer string interpolation instead of string concatenation: + <a name="string-interpolation"></a><sup>[[link](#string-interpolation)]</sup> ``` ruby # bad email_with_name = user.name + " <" + user.email + ">" @@ -501,10 +581,11 @@ ``` * Use double-quoted strings. Interpolation and escaped characters will always work without a delimiter change, and `'` is a lot more common than `"` in string literals. + <a name="double-quotes"></a><sup>[[link](#double-quotes)]</sup> ``` ruby # bad name = 'Bozhidar' @@ -513,10 +594,11 @@ ``` * Avoid using `String#+` when you need to construct large data chunks. Instead, use `String#<<`. Concatenation mutates the string instance in-place and is always faster than `String#+`, which creates a bunch of new string objects. + <a name="string-concatenation"></a><sup>[[link](#string-concatenation)]</sup> ``` ruby # good and also fast html = "" html << "<h1>Page title</h1>" @@ -524,14 +606,17 @@ paragraphs.each do |paragraph| html << "<p>#{paragraph}</p>" end ``` -## Syntax +## Methods +### Method definitions + * Use `def` with parentheses when there are arguments. Omit the parentheses when the method doesn't accept any arguments. + <a name="method-parens-when-arguments"></a><sup>[[link](#method-parens-when-arguments)]</sup> ``` ruby def some_method # body omitted end @@ -539,29 +624,34 @@ def some_method_with_arguments(arg1, arg2) # body omitted end ``` -* Never use `for`, unless you know exactly why. Most of the time iterators - should be used instead. `for` is implemented in terms of `each` (so - you're adding a level of indirection), but with a twist - `for` - doesn't introduce a new scope (unlike `each`) and variables defined - in its block will be visible outside it. +### Method calls -``` ruby -arr = [1, 2, 3] +* If the first argument to a method begins with an open parenthesis, + always use parentheses in the method invocation. For example, write + `f((3 + 2) + 1)`. + <a name="parens-no-spaces"></a><sup>[[link](#parens-no-spaces)]</sup> +* Never put a space between a method name and the opening parenthesis. + <a name="no-spaces-method-parens"></a><sup>[[link](#no-spaces-method-parens)]</sup> + +``` ruby # bad -for elem in arr do - puts elem -end +f (3 + 2) + 1 # good -arr.each { |elem| puts elem } +f(3 + 2) + 1 ``` +## Conditional Expressions + +### Conditional keywords + * Never use `then` for multi-line `if/unless`. + <a name="no-then-for-multi-line-if-unless"></a><sup>[[link](#no-then-for-multi-line-if-unless)]</sup> ``` ruby # bad if some_condition then # body omitted @@ -571,44 +661,16 @@ if some_condition # body omitted end ``` -* Avoid the ternary operator (`?:`) except in cases where all expressions are extremely - trivial. However, do use the ternary operator(`?:`) over `if/then/else/end` constructs - for single line conditionals. - -``` ruby -# bad -result = if some_condition then something else something_else end - -# good -result = some_condition ? something : something_else -``` - -* 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. - -``` ruby -# bad -some_condition ? (nested_condition ? nested_something : nested_something_else) : something_else - -# good -if some_condition - nested_condition ? nested_something : nested_something_else -else - something_else -end -``` - * The `and` and `or` keywords are banned. It's just not worth it. Always use `&&` and `||` instead. + <a name="no-and-or-or"></a><sup>[[link](#no-and-or-or)]</sup> -* Avoid multi-line `?:` (the ternary operator), use `if/unless` instead. - * Favor modifier `if/unless` usage when you have a single-line body. + <a name="favor-modifier-if-unless"></a><sup>[[link](#favor-modifier-if-unless)]</sup> ``` ruby # bad if some_condition do_something @@ -617,10 +679,11 @@ # good do_something if some_condition ``` * Never use `unless` with `else`. Rewrite these with the positive case first. + <a name="no-else-with-unless"></a><sup>[[link](#no-else-with-unless)]</sup> ``` ruby # bad unless success? puts "failure" @@ -635,10 +698,11 @@ puts "failure" end ``` * Don't use parentheses around the condition of an `if/unless/while`. + <a name="no-parens-if-unless-while"></a><sup>[[link](#no-parens-if-unless-while)]</sup> ``` ruby # bad if (x > 10) # body omitted @@ -648,15 +712,72 @@ if x > 10 # body omitted end ``` +### Ternary operator + +* Avoid the ternary operator (`?:`) except in cases where all expressions are extremely + trivial. However, do use the ternary operator(`?:`) over `if/then/else/end` constructs + for single line conditionals. + <a name="trivial-ternary"></a><sup>[[link](#trivial-ternary)]</sup> + +``` ruby +# bad +result = if some_condition then something else something_else end + +# good +result = some_condition ? something : something_else +``` + +* Avoid multi-line `?:` (the ternary operator), use `if/unless` instead. + <a name="no-multiline-ternary"></a><sup>[[link](#no-multiline-ternary)]</sup> + +* 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. + <a name="one-expression-per-branch"></a><sup>[[link](#one-expression-per-branch)]</sup> + +``` ruby +# bad +some_condition ? (nested_condition ? nested_something : nested_something_else) : something_else + +# good +if some_condition + nested_condition ? nested_something : nested_something_else +else + something_else +end +``` + +## Syntax + +* Never use `for`, unless you know exactly why. Most of the time iterators + should be used instead. `for` is implemented in terms of `each` (so + you're adding a level of indirection), but with a twist - `for` + doesn't introduce a new scope (unlike `each`) and variables defined + in its block will be visible outside it. + <a name="avoid-for"></a><sup>[[link](#avoid-for)]</sup> + +``` ruby +arr = [1, 2, 3] + +# bad +for elem in arr do + puts elem +end + +# good +arr.each { |elem| puts elem } +``` + * Prefer `{...}` over `do...end` for single-line blocks. Avoid using `{...}` for multi-line blocks (multiline chaining is always ugly). Always use `do...end` for "control flow" and "method definitions" (e.g. in Rakefiles and certain DSLs). Avoid `do...end` when chaining. + <a name="squiggly-braces"></a><sup>[[link](#squiggly-braces)]</sup> ``` ruby names = ["Bozhidar", "Steve", "Sarah"] # good @@ -674,15 +795,16 @@ names.select do |name| name.start_with?("S") 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 contents be extracted into - nifty methods? +* 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 + contents be extracted into nifty methods? * Avoid `return` where not required. + <a name="avoid-return"></a><sup>[[link](#avoid-return)]</sup> ``` ruby # bad def some_method(some_arr) return some_arr.size @@ -693,10 +815,11 @@ some_arr.size end ``` * Use spaces around the `=` operator when assigning default values to method parameters: + <a name="spaces-around-equals"></a><sup>[[link](#spaces-around-equals)]</sup> ``` ruby # bad def some_method(arg1=:default, arg2=nil, arg3=[]) # do something... @@ -710,10 +833,11 @@ While several Ruby books suggest the first style, the second is much more prominent in practice (and arguably a bit more readable). * Using the return value of `=` (an assignment) is ok. + <a name="use-return-value-of-assignment"></a><sup>[[link](#use-return-value-of-assignment)]</sup> ``` ruby # bad if (v = array.grep(/foo/)) ... @@ -723,18 +847,20 @@ # also good - has correct precedence. if (v = next_value) == "hello" ... ``` * Use `||=` freely to initialize variables. + <a name="memoization-for-initialization"></a><sup>[[link](#memoize-away)]</sup> ``` ruby # set name to Bozhidar, only if it's nil or false name ||= "Bozhidar" ``` * Don't use `||=` to initialize boolean variables. (Consider what would happen if the current value happened to be `false`.) + <a name="no-memoization-for-boolean"></a><sup>[[link](#no-memoization-for-boolean)]</sup> ``` ruby # bad - would set enabled to true even if it was false enabled ||= true @@ -744,26 +870,14 @@ * Avoid using Perl-style special variables (like `$0-9`, `$`, etc. ). They are quite cryptic and their use in anything but one-liner scripts is discouraged. Prefer long form versions such as `$PROGRAM_NAME`. + <a name="no-cryptic-vars"></a><sup>[[link](#no-cryptic-vars)]</sup> -* Never put a space between a method name and the opening parenthesis. - -``` ruby -# bad -f (3 + 2) + 1 - -# good -f(3 + 2) + 1 -``` - -* If the first argument to a method begins with an open parenthesis, - always use parentheses in the method invocation. For example, write -`f((3 + 2) + 1)`. - * Use `_` for unused block parameters. + <a name="underscore-unused-vars"></a><sup>[[link](#underscore-unused-vars)]</sup> ``` ruby # bad result = hash.map { |k, v| v + 1 } @@ -773,7 +887,10 @@ * Don't use the `===` (threequals) operator to check types. `===` is mostly an implementation detail to support Ruby features like `case`, and it's not commutative. For example, `String === "hi"` is true and `"hi" === String` is false. Instead, use `is_a?` or `kind_of?` if you must. + <a name="type-checking-is-a-kind-of"></a><sup>[[link](#type-checking-is-a-kind-of)]</sup> Refactoring is even better. It's worth looking hard at any code that explicitly checks types. + +[rubocop-guide]: https://github.com/rubocop-hq/ruby-style-guide