rubocop-github 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +33 -17
- data/STYLEGUIDE.md +395 -92
- data/config/default.yml +1400 -46
- data/config/default_cops.yml +3 -0
- data/config/default_pending.yml +6 -0
- data/config/rails.yml +364 -80
- data/config/rails_cops.yml +50 -0
- data/config/rails_pending.yml +20 -0
- data/lib/rubocop/cop/github/rails_view_render_shorthand.rb +8 -2
- data/lib/rubocop/cop/github.rb +2 -11
- data/lib/rubocop/github/inject.rb +27 -0
- data/lib/rubocop/github.rb +9 -0
- data/lib/rubocop-github-rails.rb +16 -0
- data/lib/rubocop-github.rb +9 -0
- metadata +17 -12
- data/guides/rails-render-inline.md +0 -27
- data/lib/rubocop/cop/github/rails_application_record.rb +0 -29
- data/lib/rubocop/cop/github/rails_render_inline.rb +0 -29
data/STYLEGUIDE.md
CHANGED
@@ -1,37 +1,47 @@
|
|
1
1
|
# Ruby Style Guide
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
This is GitHub's Ruby Style Guide, inspired by [RuboCop's guide][rubocop-guide].
|
4
|
+
|
5
|
+
## Table of Contents
|
6
|
+
1. [Layout](#layout)
|
7
|
+
1. [Indentation](#indentation)
|
8
|
+
2. [Inline](#inline)
|
9
|
+
3. [Newlines](#newlines)
|
10
|
+
2. [Maximum Line Length](#line-length)
|
11
|
+
3. [Classes](#classes)
|
12
|
+
4. [Collections](#collections)
|
13
|
+
5. [Documentation](#documentation)
|
14
|
+
6. [Dynamic Dispatch](#dynamic-dispatch)
|
15
|
+
7. [Exceptions](#exceptions)
|
16
|
+
8. [Hashes](#hashes)
|
17
|
+
9. [Keyword Arguments](#keyword-arguments)
|
18
|
+
10. [Naming](#naming)
|
19
|
+
11. [Percent Literals](#percent-literals)
|
20
|
+
12. [Regular Expressions](#regular-expressions)
|
21
|
+
13. [Requires](#requires)
|
22
|
+
14. [Strings](#strings)
|
23
|
+
15. [Methods](#methods)
|
24
|
+
1. [Method definitions](#method-definitions)
|
25
|
+
2. [Method calls](#method-calls)
|
26
|
+
16. [Conditional Expressions](#conditional-expressions)
|
27
|
+
1. [Conditional keywords](#conditional-keywords)
|
28
|
+
2. [Ternary operator](#ternary-operator)
|
29
|
+
17. [Syntax](#syntax)
|
30
|
+
18. [Rails](#rails)
|
31
|
+
1. [content_for](#content_for)
|
32
|
+
2. [Instance Variables in Views](#instance-variables-in-views)
|
33
|
+
|
34
|
+
## Layout
|
35
|
+
|
36
|
+
### Indentation
|
10
37
|
|
11
|
-
* Use
|
12
|
-
|
13
|
-
|
14
|
-
``` ruby
|
15
|
-
sum = 1 + 2
|
16
|
-
a, b = 1, 2
|
17
|
-
1 > 2 ? true : false; puts "Hi"
|
18
|
-
[1, 2, 3].each { |e| puts e }
|
19
|
-
```
|
20
|
-
|
21
|
-
* No spaces after `(`, `[` or before `]`, `)`.
|
22
|
-
|
23
|
-
``` ruby
|
24
|
-
some(arg).other
|
25
|
-
[1, 2, 3].length
|
26
|
-
```
|
27
|
-
|
28
|
-
* No spaces after `!`.
|
29
|
-
|
30
|
-
``` ruby
|
31
|
-
!array.include?(element)
|
32
|
-
```
|
38
|
+
* Use soft-tabs with a two space indent.
|
39
|
+
<a name="default-indentation"></a><sup>[[link](#default-indentation)]</sup>
|
40
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutindentationstyle">RuboCop rule: Layout/IndentationStyle</a>
|
33
41
|
|
34
42
|
* Indent `when` with the start of the `case` expression.
|
43
|
+
<a name="indent-when-as-start-of-case"></a><sup>[[link](#indent-when-as-start-of-case)]</sup>
|
44
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutcaseindentation">RuboCop rule: Layout/CaseIndentation</a>
|
35
45
|
|
36
46
|
``` ruby
|
37
47
|
# bad
|
@@ -71,8 +81,58 @@ else
|
|
71
81
|
end
|
72
82
|
```
|
73
83
|
|
84
|
+
### Inline
|
85
|
+
|
86
|
+
* Never leave trailing whitespace.
|
87
|
+
<a name="trailing-whitespace"></a><sup>[[link](#trailing-whitespace)]</sup>
|
88
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layouttrailingwhitespace">RuboCop rule: Layout/TrailingWhitespace</a>
|
89
|
+
|
90
|
+
* Use spaces around operators, after commas, colons and semicolons, around `{`
|
91
|
+
and before `}`.
|
92
|
+
<a name="spaces-operators"></a><sup>[[link](#spaces-operators)]</sup>
|
93
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutspacearoundoperators">RuboCop rule: Layout/SpaceAroundOperators</a>
|
94
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutspaceaftercomma">RuboCop rule: Layout/SpaceAfterComma</a>
|
95
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutspaceaftercolon">RuboCop rule: Layout/SpaceAfterColon</a>
|
96
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutspacebeforeblockbraces">RuboCop rule: Layout/SpaceBeforeBlockBraces</a>
|
97
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutspaceinsidehashliteralbraces">RuboCop rule: Layout/SpaceInsideHashLiteralBraces</a>
|
98
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylehashsyntax">RuboCop rule: Style/HashSyntax</a>
|
99
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutspacearoundoperators">RuboCop rule: Layout/SpaceAroundOperators</a>
|
100
|
+
|
101
|
+
``` ruby
|
102
|
+
sum = 1 + 2
|
103
|
+
a, b = 1, 2
|
104
|
+
1 > 2 ? true : false; puts "Hi"
|
105
|
+
[1, 2, 3].each { |e| puts e }
|
106
|
+
```
|
107
|
+
|
108
|
+
* No spaces after `(`, `[` or before `]`, `)`.
|
109
|
+
<a name="no-spaces-braces"></a><sup>[[link](#no-spaces-braces)]</sup>
|
110
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutspaceinsideparens">RuboCop rule: Layout/SpaceInsideParens</a>
|
111
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutspaceinsidereferencebrackets">RuboCop rule: Layout/SpaceInsideReferenceBrackets</a>
|
112
|
+
|
113
|
+
``` ruby
|
114
|
+
some(arg).other
|
115
|
+
[1, 2, 3].length
|
116
|
+
```
|
117
|
+
|
118
|
+
* No spaces after `!`.
|
119
|
+
<a name="no-spaces-bang"></a><sup>[[link](#no-spaces-bang)]</sup>
|
120
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutspaceafternot">RuboCop rule: Layout/SpaceAfterNot</a>
|
121
|
+
|
122
|
+
``` ruby
|
123
|
+
!array.include?(element)
|
124
|
+
```
|
125
|
+
|
126
|
+
### Newlines
|
127
|
+
|
128
|
+
* End each file with a [newline](https://github.com/bbatsov/ruby-style-guide#newline-eof).
|
129
|
+
<a name="newline-eof"></a><sup>[[link](#newline-eof)]</sup>
|
130
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layouttrailingemptylines">RuboCop rule: Layout/TrailingEmptyLines</a>
|
131
|
+
|
74
132
|
* Use empty lines between `def`s and to break up a method into logical
|
75
133
|
paragraphs.
|
134
|
+
<a name="empty-lines-def"></a><sup>[[link](#empty-lines-def)]</sup>
|
135
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutemptylinebetweendefs">RuboCop rule: Layout/EmptyLineBetweenDefs</a>
|
76
136
|
|
77
137
|
``` ruby
|
78
138
|
def some_method
|
@@ -88,10 +148,18 @@ def some_method
|
|
88
148
|
end
|
89
149
|
```
|
90
150
|
|
151
|
+
## Maximum Line Length
|
152
|
+
|
153
|
+
* 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).
|
154
|
+
<a name="line-length"></a><sup>[[link](#line-length)]</sup>
|
155
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutlinelength">RuboCop rule: Layout/LineLength</a>
|
156
|
+
|
91
157
|
## Classes
|
92
158
|
|
93
159
|
* Avoid the usage of class (`@@`) variables due to their unusual behavior
|
94
160
|
in inheritance.
|
161
|
+
<a name="class-variables"></a><sup>[[link](#class-variables)]</sup>
|
162
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleclassvars">RuboCop rule: Style/ClassVars</a>
|
95
163
|
|
96
164
|
``` ruby
|
97
165
|
class Parent
|
@@ -115,6 +183,8 @@ Parent.print_class_var # => will print "child"
|
|
115
183
|
|
116
184
|
* Use `def self.method` to define singleton methods. This makes the methods
|
117
185
|
more resistant to refactoring changes.
|
186
|
+
<a name="singleton-methods"></a><sup>[[link](#singleton-methods)]</sup>
|
187
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleclassmethodsdefinitions">RuboCop rule: Style/ClassMethodsDefinitions</a>
|
118
188
|
|
119
189
|
``` ruby
|
120
190
|
class TestClass
|
@@ -131,6 +201,8 @@ class TestClass
|
|
131
201
|
|
132
202
|
* Avoid `class << self` except when necessary, e.g. single accessors and aliased
|
133
203
|
attributes.
|
204
|
+
<a name="class-method-definitions"></a><sup>[[link](#class-method-definitions)]</sup>
|
205
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleclassmethodsdefinitions">RuboCop rule: Style/ClassMethodsDefinitions</a>
|
134
206
|
|
135
207
|
``` ruby
|
136
208
|
class TestClass
|
@@ -163,6 +235,9 @@ end
|
|
163
235
|
|
164
236
|
* Indent the `public`, `protected`, and `private` methods as much the
|
165
237
|
method definitions they apply to. Leave one blank line above them.
|
238
|
+
<a name="access-modifier-identation"></a><sup>[[link](#access-modifier-identation)]</sup>
|
239
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutaccessmodifierindentation">RuboCop rule: Layout/AccessModifierIndentation</a>
|
240
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_layout.html#layoutemptylinesaroundaccessmodifier">RuboCop rule: Layout/EmptyLinesAroundAccessModifier</a>
|
166
241
|
|
167
242
|
``` ruby
|
168
243
|
class SomeClass
|
@@ -179,6 +254,8 @@ end
|
|
179
254
|
|
180
255
|
* Avoid explicit use of `self` as the recipient of internal class or instance
|
181
256
|
messages unless to specify a method shadowed by a variable.
|
257
|
+
<a name="self-messages"></a><sup>[[link](#self-messages)]</sup>
|
258
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleredundantself">RuboCop rule: Style/RedundantSelf</a>
|
182
259
|
|
183
260
|
``` ruby
|
184
261
|
class SomeClass
|
@@ -195,6 +272,8 @@ end
|
|
195
272
|
|
196
273
|
* Prefer `%w` to the literal array syntax when you need an array of
|
197
274
|
strings.
|
275
|
+
<a name="percent-w"></a><sup>[[link](#percent-w)]</sup>
|
276
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylewordarray">RuboCop rule: Style/WordArray</a>
|
198
277
|
|
199
278
|
``` ruby
|
200
279
|
# bad
|
@@ -208,8 +287,11 @@ STATES = %w(draft open closed)
|
|
208
287
|
implements a collection of unordered values with no duplicates. This
|
209
288
|
is a hybrid of `Array`'s intuitive inter-operation facilities and
|
210
289
|
`Hash`'s fast lookup.
|
290
|
+
<a name="prefer-set"></a><sup>[[link](#prefer-set)]</sup>
|
211
291
|
|
212
292
|
* Use symbols instead of strings as hash keys.
|
293
|
+
<a name="symbols-as-keys"></a><sup>[[link](#symbols-as-keys)]</sup>
|
294
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylestringhashkeys">RuboCop rule: Style/StringHashKeys</a>
|
213
295
|
|
214
296
|
``` ruby
|
215
297
|
# bad
|
@@ -222,6 +304,7 @@ hash = { one: 1, two: 2, three: 3 }
|
|
222
304
|
## Documentation
|
223
305
|
|
224
306
|
Use [TomDoc](http://tomdoc.org) to the best of your ability. It's pretty sweet:
|
307
|
+
<a name="tomdoc"></a><sup>[[link](#tomdoc)]</sup>
|
225
308
|
|
226
309
|
``` ruby
|
227
310
|
# Public: Duplicate some text an arbitrary number of times.
|
@@ -243,9 +326,11 @@ end
|
|
243
326
|
## Dynamic Dispatch
|
244
327
|
|
245
328
|
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:
|
329
|
+
<a name="avoid-send"></a><sup>[[link](#avoid-send)]</sup>
|
330
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylesend">RuboCop rule: Style/Send</a>
|
246
331
|
|
247
332
|
``` ruby
|
248
|
-
# avoid
|
333
|
+
# avoid
|
249
334
|
unless [:base, :head].include?(base_or_head)
|
250
335
|
raise ArgumentError, "base_or_head must be either :base or :head"
|
251
336
|
end
|
@@ -268,6 +353,7 @@ end
|
|
268
353
|
## Exceptions
|
269
354
|
|
270
355
|
* Don't use exceptions for flow of control.
|
356
|
+
<a name="exceptions-flow-control"></a><sup>[[link](#exceptions-flow-control)]</sup>
|
271
357
|
|
272
358
|
``` ruby
|
273
359
|
# bad
|
@@ -286,6 +372,7 @@ end
|
|
286
372
|
```
|
287
373
|
|
288
374
|
* Rescue specific exceptions, not `StandardError` or its superclasses.
|
375
|
+
<a name="specific-exceptions"></a><sup>[[link](#specific-exceptions)]</sup>
|
289
376
|
|
290
377
|
``` ruby
|
291
378
|
# bad
|
@@ -306,6 +393,8 @@ end
|
|
306
393
|
## Hashes
|
307
394
|
|
308
395
|
Use the Ruby 1.9 syntax for hash literals when all the keys are symbols:
|
396
|
+
<a name="symbols-as-hash-keys"></a><sup>[[link](#symbols-as-hash-keys)]</sup>
|
397
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylestringhashkeys">RuboCop rule: Style/StringHashKeys</a>
|
309
398
|
|
310
399
|
``` ruby
|
311
400
|
# bad
|
@@ -322,6 +411,7 @@ user = {
|
|
322
411
|
```
|
323
412
|
|
324
413
|
Use the 1.9 syntax when calling a method with Hash options arguments or named arguments:
|
414
|
+
<a name="symbols-as-hash-method-arguments"></a><sup>[[link](#symbols-as-hash-method-arguments)]</sup>
|
325
415
|
|
326
416
|
``` ruby
|
327
417
|
# bad
|
@@ -334,6 +424,10 @@ link_to("Account", controller: "users", action: "show", id: user)
|
|
334
424
|
```
|
335
425
|
|
336
426
|
If you have a hash with mixed key types, use the legacy hashrocket style to avoid mixing styles within the same hash:
|
427
|
+
<a name="consistent-hash-syntax"></a><sup>[[link](#consistent-hash-syntax)]</sup>
|
428
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylehashsyntax">RuboCop rule: Style/HashSyntax</a>
|
429
|
+
|
430
|
+
``` ruby
|
337
431
|
|
338
432
|
``` ruby
|
339
433
|
# bad
|
@@ -352,8 +446,11 @@ hsh = {
|
|
352
446
|
## Keyword Arguments
|
353
447
|
|
354
448
|
[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.
|
449
|
+
<a name="keyword-arguments"></a><sup>[[link](#keyword-arguments)]</sup>
|
450
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleoptionalbooleanparameter">RuboCop rule: Style/OptionalBooleanParameter</a>
|
355
451
|
|
356
452
|
So instead of this:
|
453
|
+
|
357
454
|
``` ruby
|
358
455
|
def remove_member(user, skip_membership_check=false)
|
359
456
|
# ...
|
@@ -363,7 +460,8 @@ end
|
|
363
460
|
remove_member(user, true)
|
364
461
|
```
|
365
462
|
|
366
|
-
Do this, which is much clearer
|
463
|
+
Do this, which is much clearer:
|
464
|
+
|
367
465
|
``` ruby
|
368
466
|
def remove_member(user, skip_membership_check: false)
|
369
467
|
# ...
|
@@ -376,23 +474,35 @@ remove_member(user, skip_membership_check: true)
|
|
376
474
|
## Naming
|
377
475
|
|
378
476
|
* Use `snake_case` for methods and variables.
|
477
|
+
<a name="snake-case-methods-vars"></a><sup>[[link](#snake-case-methods-vars)]</sup>
|
478
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_naming.html#namingsnakecase">RuboCop rule: Naming/SnakeCase</a>
|
479
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_naming.html#namingvariablename">RuboCop rule: Naming/VariableName</a>
|
379
480
|
|
380
481
|
* Use `CamelCase` for classes and modules. (Keep acronyms like HTTP,
|
381
482
|
RFC, XML uppercase.)
|
483
|
+
<a name="camelcase-classes-modules"></a><sup>[[link](#camelcase-classes-modules)]</sup>
|
484
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_naming.html#namingclassandmodulecamelcase">RuboCop rule: Naming/ClassAndModuleCamelCase</a>
|
382
485
|
|
383
486
|
* Use `SCREAMING_SNAKE_CASE` for other constants.
|
487
|
+
<a name="screaming-snake-case-constants"></a><sup>[[link](#screaming-snake-case-constants)]</sup>
|
488
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_naming.html#namingconstantname">RuboCop rule: Naming/ConstantName</a>
|
384
489
|
|
385
490
|
* The names of predicate methods (methods that return a boolean value)
|
386
491
|
should end in a question mark. (i.e. `Array#empty?`).
|
492
|
+
<a name="bool-methods-qmark"></a><sup>[[link](#bool-methods-qmark)]</sup>
|
493
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_naming.html#namingpredicatename">RuboCop rule: Naming/PredicateName</a>
|
387
494
|
|
388
495
|
* The names of potentially "dangerous" methods (i.e. methods that modify `self` or the
|
389
496
|
arguments, `exit!`, etc.) should end with an exclamation mark. Bang methods
|
390
|
-
should only exist if a non-bang counterpart (method name which does NOT end with !)
|
497
|
+
should only exist if a non-bang counterpart (method name which does NOT end with !)
|
391
498
|
also exists.
|
499
|
+
<a name="dangerous-method-bang"></a><sup>[[link](#dangerous-method-bang)]</sup>
|
392
500
|
|
393
501
|
## Percent Literals
|
394
502
|
|
395
503
|
* Use `%w` freely.
|
504
|
+
<a name="use-percent-w-freely"></a><sup>[[link](#use-percent-w-freely)]</sup>
|
505
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylewordarray">RuboCop rule: Style/WordArray</a>
|
396
506
|
|
397
507
|
``` ruby
|
398
508
|
STATES = %w(draft open closed)
|
@@ -400,6 +510,8 @@ STATES = %w(draft open closed)
|
|
400
510
|
|
401
511
|
* Use `%()` for single-line strings which require both interpolation
|
402
512
|
and embedded double-quotes. For multi-line strings, prefer heredocs.
|
513
|
+
<a name="percent-parens-single-line"></a><sup>[[link](#percent-parens-single-line)]</sup>
|
514
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylebarepercentliterals">RuboCop rule: Style/BarePercentLiterals</a>
|
403
515
|
|
404
516
|
``` ruby
|
405
517
|
# bad (no interpolation needed)
|
@@ -419,6 +531,8 @@ STATES = %w(draft open closed)
|
|
419
531
|
```
|
420
532
|
|
421
533
|
* Use `%r` only for regular expressions matching *more than* one '/' character.
|
534
|
+
<a name="percent-r-regular-expressions"></a><sup>[[link](#percent-r-regular-expressions)]</sup>
|
535
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleregexpliteral">RuboCop rule: Style/RegexpLiteral</a>
|
422
536
|
|
423
537
|
``` ruby
|
424
538
|
# bad
|
@@ -436,7 +550,8 @@ STATES = %w(draft open closed)
|
|
436
550
|
|
437
551
|
* Avoid using $1-9 as it can be hard to track what they contain. Named groups
|
438
552
|
can be used instead.
|
439
|
-
|
553
|
+
<a name="capture-with-named-groups"></a><sup>[[link](#capture-with-named-groups)]</sup>
|
554
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_lint.html#mixedregexpcapturetypes">RuboCop rule: Lint/MixedRegexpCaptureTypes</a>
|
440
555
|
``` ruby
|
441
556
|
# bad
|
442
557
|
/(regexp)/ =~ string
|
@@ -451,6 +566,7 @@ process meaningful_var
|
|
451
566
|
|
452
567
|
* Be careful with `^` and `$` as they match start/end of line, not string endings.
|
453
568
|
If you want to match the whole string use: `\A` and `\z`.
|
569
|
+
<a name="regex-begin-end-markers"></a><sup>[[link](#regex-begin-end-markers)]</sup>
|
454
570
|
|
455
571
|
``` ruby
|
456
572
|
string = "some injection\nusername"
|
@@ -460,6 +576,7 @@ string[/\Ausername\z/] # don't match
|
|
460
576
|
|
461
577
|
* Use `x` modifier for complex regexps. This makes them more readable and you
|
462
578
|
can add some useful comments. Just be careful as spaces are ignored.
|
579
|
+
<a name="x-modifier-complex-regex"></a><sup>[[link](#x-modifier-complex-regex)]</sup>
|
463
580
|
|
464
581
|
``` ruby
|
465
582
|
regexp = %r{
|
@@ -476,6 +593,7 @@ regexp = %r{
|
|
476
593
|
Always `require` dependencies used directly in a script at the start of the same file.
|
477
594
|
Resources that will get autoloaded on first use—such as Rails models, controllers, or
|
478
595
|
helpers—don't need to be required.
|
596
|
+
<a name="require-dependencies-directly"></a><sup>[[link](#require-dependencies-directly)]</sup>
|
479
597
|
|
480
598
|
``` ruby
|
481
599
|
require "set"
|
@@ -491,6 +609,8 @@ documentation about the libraries that the current file uses.
|
|
491
609
|
## Strings
|
492
610
|
|
493
611
|
* Prefer string interpolation instead of string concatenation:
|
612
|
+
<a name="string-interpolation"></a><sup>[[link](#string-interpolation)]</sup>
|
613
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylestringconcatenation">RuboCop rule: Style/StringConcatenation</a>
|
494
614
|
|
495
615
|
``` ruby
|
496
616
|
# bad
|
@@ -503,6 +623,8 @@ email_with_name = "#{user.name} <#{user.email}>"
|
|
503
623
|
* Use double-quoted strings. Interpolation and escaped characters
|
504
624
|
will always work without a delimiter change, and `'` is a lot more
|
505
625
|
common than `"` in string literals.
|
626
|
+
<a name="double-quotes"></a><sup>[[link](#double-quotes)]</sup>
|
627
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylestringliterals">RuboCop rule: Style/StringLiterals</a>
|
506
628
|
|
507
629
|
``` ruby
|
508
630
|
# bad
|
@@ -515,6 +637,7 @@ name = "Bozhidar"
|
|
515
637
|
* Avoid using `String#+` when you need to construct large data chunks.
|
516
638
|
Instead, use `String#<<`. Concatenation mutates the string instance in-place
|
517
639
|
and is always faster than `String#+`, which creates a bunch of new string objects.
|
640
|
+
<a name="string-concatenation"></a><sup>[[link](#string-concatenation)]</sup>
|
518
641
|
|
519
642
|
``` ruby
|
520
643
|
# good and also fast
|
@@ -526,10 +649,14 @@ paragraphs.each do |paragraph|
|
|
526
649
|
end
|
527
650
|
```
|
528
651
|
|
529
|
-
##
|
652
|
+
## Methods
|
653
|
+
|
654
|
+
### Method definitions
|
530
655
|
|
531
656
|
* Use `def` with parentheses when there are arguments. Omit the
|
532
657
|
parentheses when the method doesn't accept any arguments.
|
658
|
+
<a name="method-parens-when-arguments"></a><sup>[[link](#method-parens-when-arguments)]</sup>
|
659
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styledefwithparentheses">RuboCop rule: Style/DefWithParentheses</a>
|
533
660
|
|
534
661
|
``` ruby
|
535
662
|
def some_method
|
@@ -541,25 +668,33 @@ end
|
|
541
668
|
end
|
542
669
|
```
|
543
670
|
|
544
|
-
|
545
|
-
should be used instead. `for` is implemented in terms of `each` (so
|
546
|
-
you're adding a level of indirection), but with a twist - `for`
|
547
|
-
doesn't introduce a new scope (unlike `each`) and variables defined
|
548
|
-
in its block will be visible outside it.
|
671
|
+
### Method calls
|
549
672
|
|
550
|
-
|
551
|
-
|
673
|
+
* If the first argument to a method begins with an open parenthesis,
|
674
|
+
always use parentheses in the method invocation. For example, write
|
675
|
+
`f((3 + 2) + 1)`.
|
676
|
+
<a name="parens-no-spaces"></a><sup>[[link](#parens-no-spaces)]</sup>
|
677
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylemethodcallwithargsparentheses">RuboCop rule: Style/MethodCallWithArgsParentheses</a>
|
552
678
|
|
679
|
+
* Never put a space between a method name and the opening parenthesis.
|
680
|
+
<a name="no-spaces-method-parens"></a><sup>[[link](#no-spaces-method-parens)]</sup>
|
681
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleparenthesesasgroupedexpression">RuboCop rule: Style/ParenthesesAsGroupedExpression</a>
|
682
|
+
|
683
|
+
``` ruby
|
553
684
|
# bad
|
554
|
-
|
555
|
-
puts elem
|
556
|
-
end
|
685
|
+
f (3 + 2) + 1
|
557
686
|
|
558
687
|
# good
|
559
|
-
|
688
|
+
f(3 + 2) + 1
|
560
689
|
```
|
561
690
|
|
691
|
+
## Conditional Expressions
|
692
|
+
|
693
|
+
### Conditional keywords
|
694
|
+
|
562
695
|
* Never use `then` for multi-line `if/unless`.
|
696
|
+
<a name="no-then-for-multi-line-if-unless"></a><sup>[[link](#no-then-for-multi-line-if-unless)]</sup>
|
697
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylemultilineifthen">RuboCop rule: Style/MultilineIfThen</a>
|
563
698
|
|
564
699
|
``` ruby
|
565
700
|
# bad
|
@@ -573,40 +708,14 @@ if some_condition
|
|
573
708
|
end
|
574
709
|
```
|
575
710
|
|
576
|
-
* Avoid the ternary operator (`?:`) except in cases where all expressions are extremely
|
577
|
-
trivial. However, do use the ternary operator(`?:`) over `if/then/else/end` constructs
|
578
|
-
for single line conditionals.
|
579
|
-
|
580
|
-
``` ruby
|
581
|
-
# bad
|
582
|
-
result = if some_condition then something else something_else end
|
583
|
-
|
584
|
-
# good
|
585
|
-
result = some_condition ? something : something_else
|
586
|
-
```
|
587
|
-
|
588
|
-
* Use one expression per branch in a ternary operator. This
|
589
|
-
also means that ternary operators must not be nested. Prefer
|
590
|
-
`if/else` constructs in these cases.
|
591
|
-
|
592
|
-
``` ruby
|
593
|
-
# bad
|
594
|
-
some_condition ? (nested_condition ? nested_something : nested_something_else) : something_else
|
595
|
-
|
596
|
-
# good
|
597
|
-
if some_condition
|
598
|
-
nested_condition ? nested_something : nested_something_else
|
599
|
-
else
|
600
|
-
something_else
|
601
|
-
end
|
602
|
-
```
|
603
|
-
|
604
711
|
* The `and` and `or` keywords are banned. It's just not worth it. Always use `&&` and `||` instead.
|
605
|
-
|
606
|
-
*
|
712
|
+
<a name="no-and-or-or"></a><sup>[[link](#no-and-or-or)]</sup>
|
713
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleandor">RuboCop rule: Style/AndOr</a>
|
607
714
|
|
608
715
|
* Favor modifier `if/unless` usage when you have a single-line
|
609
716
|
body.
|
717
|
+
<a name="favor-modifier-if-unless"></a><sup>[[link](#favor-modifier-if-unless)]</sup>
|
718
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylemultilineternaryoperator">RuboCop rule: Style/MultilineTernaryOperator</a>
|
610
719
|
|
611
720
|
``` ruby
|
612
721
|
# bad
|
@@ -619,6 +728,8 @@ do_something if some_condition
|
|
619
728
|
```
|
620
729
|
|
621
730
|
* Never use `unless` with `else`. Rewrite these with the positive case first.
|
731
|
+
<a name="no-else-with-unless"></a><sup>[[link](#no-else-with-unless)]</sup>
|
732
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleunlesselse">RuboCop rule: Style/UnlessElse</a>
|
622
733
|
|
623
734
|
``` ruby
|
624
735
|
# bad
|
@@ -637,6 +748,8 @@ end
|
|
637
748
|
```
|
638
749
|
|
639
750
|
* Don't use parentheses around the condition of an `if/unless/while`.
|
751
|
+
<a name="no-parens-if-unless-while"></a><sup>[[link](#no-parens-if-unless-while)]</sup>
|
752
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleparenthesesaroundcondition">RuboCop rule: Style/ParenthesesAroundCondition</a>
|
640
753
|
|
641
754
|
``` ruby
|
642
755
|
# bad
|
@@ -650,11 +763,73 @@ if x > 10
|
|
650
763
|
end
|
651
764
|
```
|
652
765
|
|
766
|
+
### Ternary operator
|
767
|
+
|
768
|
+
* Avoid the ternary operator (`?:`) except in cases where all expressions are extremely
|
769
|
+
trivial. However, do use the ternary operator(`?:`) over `if/then/else/end` constructs
|
770
|
+
for single line conditionals.
|
771
|
+
<a name="trivial-ternary"></a><sup>[[link](#trivial-ternary)]</sup>
|
772
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylemultilineternaryoperator">RuboCop rule: Style/MultilineTernaryOperator</a>
|
773
|
+
|
774
|
+
``` ruby
|
775
|
+
# bad
|
776
|
+
result = if some_condition then something else something_else end
|
777
|
+
|
778
|
+
# good
|
779
|
+
result = some_condition ? something : something_else
|
780
|
+
```
|
781
|
+
|
782
|
+
* Avoid multi-line `?:` (the ternary operator), use `if/unless` instead.
|
783
|
+
<a name="no-multiline-ternary"></a><sup>[[link](#no-multiline-ternary)]</sup>
|
784
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylemultilineternaryoperator">RuboCop rule: Style/MultilineTernaryOperator</a>
|
785
|
+
|
786
|
+
* Use one expression per branch in a ternary operator. This
|
787
|
+
also means that ternary operators must not be nested. Prefer
|
788
|
+
`if/else` constructs in these cases.
|
789
|
+
<a name="one-expression-per-branch"></a><sup>[[link](#one-expression-per-branch)]</sup>
|
790
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylenestedternaryoperator">RuboCop rule: Style/NestedTernaryOperator</a>
|
791
|
+
|
792
|
+
``` ruby
|
793
|
+
# bad
|
794
|
+
some_condition ? (nested_condition ? nested_something : nested_something_else) : something_else
|
795
|
+
|
796
|
+
# good
|
797
|
+
if some_condition
|
798
|
+
nested_condition ? nested_something : nested_something_else
|
799
|
+
else
|
800
|
+
something_else
|
801
|
+
end
|
802
|
+
```
|
803
|
+
|
804
|
+
## Syntax
|
805
|
+
|
806
|
+
* Never use `for`, unless you know exactly why. Most of the time iterators
|
807
|
+
should be used instead. `for` is implemented in terms of `each` (so
|
808
|
+
you're adding a level of indirection), but with a twist - `for`
|
809
|
+
doesn't introduce a new scope (unlike `each`) and variables defined
|
810
|
+
in its block will be visible outside it.
|
811
|
+
<a name="avoid-for"></a><sup>[[link](#avoid-for)]</sup>
|
812
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylefor">RuboCop rule: Style/For</a>
|
813
|
+
|
814
|
+
``` ruby
|
815
|
+
arr = [1, 2, 3]
|
816
|
+
|
817
|
+
# bad
|
818
|
+
for elem in arr do
|
819
|
+
puts elem
|
820
|
+
end
|
821
|
+
|
822
|
+
# good
|
823
|
+
arr.each { |elem| puts elem }
|
824
|
+
```
|
825
|
+
|
653
826
|
* Prefer `{...}` over `do...end` for single-line blocks. Avoid using
|
654
827
|
`{...}` for multi-line blocks (multiline chaining is always
|
655
828
|
ugly). Always use `do...end` for "control flow" and "method
|
656
829
|
definitions" (e.g. in Rakefiles and certain DSLs). Avoid `do...end`
|
657
830
|
when chaining.
|
831
|
+
<a name="squiggly-braces"></a><sup>[[link](#squiggly-braces)]</sup>
|
832
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleblockdelimiters">RuboCop rule: Style/BlockDelimiters</a>
|
658
833
|
|
659
834
|
``` ruby
|
660
835
|
names = ["Bozhidar", "Steve", "Sarah"]
|
@@ -676,11 +851,13 @@ names.select do |name|
|
|
676
851
|
end.map { |name| name.upcase }
|
677
852
|
```
|
678
853
|
|
679
|
-
|
680
|
-
|
681
|
-
|
854
|
+
* Some will argue that multiline chaining would look OK with the use of `{...}`,
|
855
|
+
but they should ask themselves: is this code really readable and can't the block's
|
856
|
+
contents be extracted into nifty methods?
|
682
857
|
|
683
858
|
* Avoid `return` where not required.
|
859
|
+
<a name="avoid-return"></a><sup>[[link](#avoid-return)]</sup>
|
860
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleredundantreturn">RuboCop rule: Style/RedundantReturn</a>
|
684
861
|
|
685
862
|
``` ruby
|
686
863
|
# bad
|
@@ -695,6 +872,8 @@ end
|
|
695
872
|
```
|
696
873
|
|
697
874
|
* Use spaces around the `=` operator when assigning default values to method parameters:
|
875
|
+
<a name="spaces-around-equals"></a><sup>[[link](#spaces-around-equals)]</sup>
|
876
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylespacearoundequalsinparameterdefault">RuboCop rule: Style/SpaceAroundEqualsInParameterDefault</a>
|
698
877
|
|
699
878
|
``` ruby
|
700
879
|
# bad
|
@@ -712,6 +891,7 @@ While several Ruby books suggest the first style, the second is much more promin
|
|
712
891
|
in practice (and arguably a bit more readable).
|
713
892
|
|
714
893
|
* Using the return value of `=` (an assignment) is ok.
|
894
|
+
<a name="use-return-value-of-assignment"></a><sup>[[link](#use-return-value-of-assignment)]</sup>
|
715
895
|
|
716
896
|
``` ruby
|
717
897
|
# bad
|
@@ -725,6 +905,8 @@ if (v = next_value) == "hello" ...
|
|
725
905
|
```
|
726
906
|
|
727
907
|
* Use `||=` freely to initialize variables.
|
908
|
+
<a name="memoization-for-initialization"></a><sup>[[link](#memoize-away)]</sup>
|
909
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleorassignment">RuboCop rule: Style/OrAssignment</a>
|
728
910
|
|
729
911
|
``` ruby
|
730
912
|
# set name to Bozhidar, only if it's nil or false
|
@@ -733,6 +915,8 @@ name ||= "Bozhidar"
|
|
733
915
|
|
734
916
|
* Don't use `||=` to initialize boolean variables. (Consider what
|
735
917
|
would happen if the current value happened to be `false`.)
|
918
|
+
<a name="no-memoization-for-boolean"></a><sup>[[link](#no-memoization-for-boolean)]</sup>
|
919
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#styleorassignment">RuboCop rule: Style/OrAssignment</a>
|
736
920
|
|
737
921
|
``` ruby
|
738
922
|
# bad - would set enabled to true even if it was false
|
@@ -746,22 +930,12 @@ enabled = true if enabled.nil?
|
|
746
930
|
etc. ). They are quite cryptic and their use in anything but
|
747
931
|
one-liner scripts is discouraged. Prefer long form versions such as
|
748
932
|
`$PROGRAM_NAME`.
|
749
|
-
|
750
|
-
*
|
751
|
-
|
752
|
-
``` ruby
|
753
|
-
# bad
|
754
|
-
f (3 + 2) + 1
|
755
|
-
|
756
|
-
# good
|
757
|
-
f(3 + 2) + 1
|
758
|
-
```
|
759
|
-
|
760
|
-
* If the first argument to a method begins with an open parenthesis,
|
761
|
-
always use parentheses in the method invocation. For example, write
|
762
|
-
`f((3 + 2) + 1)`.
|
933
|
+
<a name="no-cryptic-vars"></a><sup>[[link](#no-cryptic-vars)]</sup>
|
934
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylespecialglobalvars">RuboCop rule: Style/SpecialGlobalVars</a>
|
763
935
|
|
764
936
|
* Use `_` for unused block parameters.
|
937
|
+
<a name="underscore-unused-vars"></a><sup>[[link](#underscore-unused-vars)]</sup>
|
938
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_lint.html#lintunusedblockargument">RuboCop rule: Lint/UnusedBlockArgument</a>
|
765
939
|
|
766
940
|
``` ruby
|
767
941
|
# bad
|
@@ -775,5 +949,134 @@ result = hash.map { |_, v| v + 1 }
|
|
775
949
|
implementation detail to support Ruby features like `case`, and it's not commutative.
|
776
950
|
For example, `String === "hi"` is true and `"hi" === String` is false.
|
777
951
|
Instead, use `is_a?` or `kind_of?` if you must.
|
952
|
+
<a name="type-checking-is-a-kind-of"></a><sup>[[link](#type-checking-is-a-kind-of)]</sup>
|
953
|
+
* <a href="https://docs.rubocop.org/rubocop/cops_style.html#stylecaseequality">RuboCop rule: Style/CaseEquality</a>
|
778
954
|
|
779
955
|
Refactoring is even better. It's worth looking hard at any code that explicitly checks types.
|
956
|
+
|
957
|
+
## Rails
|
958
|
+
|
959
|
+
### content_for
|
960
|
+
|
961
|
+
Limit usage of `content_for` helper. The use of `content_for` is the same as setting an instance variable plus `capture`.
|
962
|
+
|
963
|
+
``` erb
|
964
|
+
<% content_for :foo do %>
|
965
|
+
Hello
|
966
|
+
<% end %>
|
967
|
+
```
|
968
|
+
|
969
|
+
Is effectively the same as
|
970
|
+
|
971
|
+
``` erb
|
972
|
+
<% @foo_content = capture do %>
|
973
|
+
Hello
|
974
|
+
<% end %>
|
975
|
+
```
|
976
|
+
|
977
|
+
See "Instance Variables in Views" below.
|
978
|
+
|
979
|
+
#### Common Anti-patterns
|
980
|
+
|
981
|
+
**Using `content_for` within the same template to capture data.**
|
982
|
+
|
983
|
+
Instead, just use `capture`.
|
984
|
+
|
985
|
+
``` erb
|
986
|
+
<!-- bad -->
|
987
|
+
<% content_for :page do %>
|
988
|
+
Hello
|
989
|
+
<% end %>
|
990
|
+
<% if foo? %>
|
991
|
+
<div class="container">
|
992
|
+
<%= yield :page %>
|
993
|
+
</div>
|
994
|
+
<% else %>
|
995
|
+
<%= yield :page %>
|
996
|
+
<% end %>
|
997
|
+
```
|
998
|
+
|
999
|
+
Simply capture and use a local variable since the result is only needed in this template.
|
1000
|
+
|
1001
|
+
``` erb
|
1002
|
+
<!-- good -->
|
1003
|
+
<% page = capture do %>
|
1004
|
+
Hello
|
1005
|
+
<% end %>
|
1006
|
+
<% if foo? %>
|
1007
|
+
<div class="container">
|
1008
|
+
<%= page %>
|
1009
|
+
</div>
|
1010
|
+
<% else %>
|
1011
|
+
<%= page %>
|
1012
|
+
<% end %>
|
1013
|
+
```
|
1014
|
+
|
1015
|
+
**Using `content_for` to pass content to a subtemplate.**
|
1016
|
+
|
1017
|
+
Instead, `render layout:` with a block.
|
1018
|
+
|
1019
|
+
``` erb
|
1020
|
+
<!-- bad -->
|
1021
|
+
<% content_for :page do %>
|
1022
|
+
Hello
|
1023
|
+
<% end %>
|
1024
|
+
<%= render partial: "page" %>
|
1025
|
+
<!-- _page.html.erb -->
|
1026
|
+
<div class="container">
|
1027
|
+
<%= yield :page %>
|
1028
|
+
</div>
|
1029
|
+
```
|
1030
|
+
|
1031
|
+
Pass the content in a block directly to the `render` function.
|
1032
|
+
|
1033
|
+
``` erb
|
1034
|
+
<!-- good -->
|
1035
|
+
<%= render layout: "page" do %>
|
1036
|
+
Hello
|
1037
|
+
<% end %>
|
1038
|
+
<!-- _page.html.erb -->
|
1039
|
+
<div class="container">
|
1040
|
+
<%= yield %>
|
1041
|
+
</div>
|
1042
|
+
```
|
1043
|
+
|
1044
|
+
### Instance Variables in Views
|
1045
|
+
|
1046
|
+
In general, passing data between templates with instance variables is discouraged. This even applies from controllers to templates, not just between partials.
|
1047
|
+
|
1048
|
+
`:locals` can be used to pass data from a controller just like partials.
|
1049
|
+
|
1050
|
+
``` ruby
|
1051
|
+
def show
|
1052
|
+
render "blob/show", locals: {
|
1053
|
+
:repository => current_repository,
|
1054
|
+
:commit => current_commit,
|
1055
|
+
:blob => current_blob
|
1056
|
+
}
|
1057
|
+
end
|
1058
|
+
```
|
1059
|
+
|
1060
|
+
Rails implicit renders are also discouraged.
|
1061
|
+
|
1062
|
+
Always explicitly render templates with a full directory path. This makes template callers easier to trace. You can find all the callers of `"app/view/site/hompage.html.erb"` with a simple project search for `"site/homepage"`.
|
1063
|
+
|
1064
|
+
``` ruby
|
1065
|
+
def homepage
|
1066
|
+
render "site/homepage"
|
1067
|
+
end
|
1068
|
+
```
|
1069
|
+
|
1070
|
+
#### Exceptions
|
1071
|
+
|
1072
|
+
There are some known edge cases where you might be forced to use instance variables. In these cases, its okay to do so.
|
1073
|
+
|
1074
|
+
##### Legacy templates
|
1075
|
+
|
1076
|
+
If you need to call a subview that expects an instance variable be set. If possible consider refactoring the subview to accept a local instead.
|
1077
|
+
|
1078
|
+
##### Layouts
|
1079
|
+
|
1080
|
+
Unfortunately the only way to get data into a layout template is with instance variables. You can't explicitly pass locals to them.
|
1081
|
+
|
1082
|
+
[rubocop-guide]: https://github.com/rubocop-hq/ruby-style-guide
|