rubocop-hk 1.0.9

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.
data/STYLEGUIDE.md ADDED
@@ -0,0 +1,1660 @@
1
+ <div align="center">
2
+
3
+ # 🎨 Ruby Style Guide - RuboCop HK
4
+
5
+ > **The complete coding standards and conventions used by RuboCop HK**
6
+
7
+ [![RuboCop](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop)
8
+ [![Ruby Style Guide](https://img.shields.io/badge/ruby-style_guide-red.svg)](https://rubystyle.guide)
9
+ [![Rails](https://img.shields.io/badge/rails-conventions-red.svg)](https://rubyonrails.org)
10
+
11
+ **[📚 Back to README](README.md) • [⚡ Quick Start](QUICK_START.md) • [📖 Usage Guide](USAGE.md) • [⚙️ Customization](CUSTOMIZATION.md)**
12
+
13
+ </div>
14
+
15
+ ---
16
+
17
+ ## 📋 Table of Contents
18
+ 1. [Whitespace](#whitespace)
19
+ 1. [Indentation](#indentation)
20
+ 1. [Inline](#inline)
21
+ 1. [Newlines](#newlines)
22
+ 1. [Line Length](#line-length)
23
+ 1. [Commenting](#commenting)
24
+ 1. [Block and inline comments](#block-and-inline-comments)
25
+ 1. [Punctuation, spelling, and grammar](#punctuation-spelling-and-grammar)
26
+ 1. [TODO comments](#todo-comments)
27
+ 1. [Commented-out code](#commented-out-code)
28
+ 1. [Methods](#methods)
29
+ 1. [Method definitions](#method-definitions)
30
+ 1. [Method calls](#method-calls)
31
+ 1. [Conditional Expressions](#conditional-expressions)
32
+ 1. [Conditional keywords](#conditional-keywords)
33
+ 1. [Ternary operator](#ternary-operator)
34
+ 1. [Syntax](#syntax)
35
+ 1. [Naming](#naming)
36
+ 1. [Classes](#classes)
37
+ 1. [Exceptions](#exceptions)
38
+ 1. [Collections](#collections)
39
+ 1. [Strings](#strings)
40
+ 1. [Regular Expressions](#regular-expressions)
41
+ 1. [Percent Literals](#percent-literals)
42
+ 1. [Rails](#rails)
43
+ 1. [Scopes](#scopes)
44
+ 1. [Be Consistent](#be-consistent)
45
+ 1. [Translation](#translation)
46
+
47
+ ## Whitespace
48
+
49
+ ### Indentation
50
+
51
+ * <a name="default-indentation"></a>Use soft-tabs with a
52
+ two-space indent.<sup>[[link](#default-indentation)]</sup>
53
+
54
+ * <a name="indent-when-as-case"></a>Indent `when` as deep as `case`.
55
+ <sup>[[link](#indent-when-as-case)]</sup>
56
+
57
+ ```ruby
58
+ case
59
+ when song.name == "Misty"
60
+ puts "Not again!"
61
+ when song.duration > 120
62
+ puts "Too long!"
63
+ when Time.now.hour > 21
64
+ puts "It's too late"
65
+ else
66
+ song.play
67
+ end
68
+
69
+ kind = case year
70
+ when 1850..1889 then "Blues"
71
+ when 1890..1909 then "Ragtime"
72
+ when 1910..1929 then "New Orleans Jazz"
73
+ when 1930..1939 then "Swing"
74
+ when 1940..1950 then "Bebop"
75
+ else "Jazz"
76
+ end
77
+ ```
78
+
79
+ * <a name="align-function-params"></a>Align function parameters either all on
80
+ the same line or one per line.<sup>[[link](#align-function-params)]</sup>
81
+
82
+ ```ruby
83
+ # bad
84
+ def self.create_translation(phrase_id, phrase_key, target_locale,
85
+ value, user_id, do_xss_check, allow_verification)
86
+ ...
87
+ end
88
+
89
+ # good
90
+ def self.create_translation(phrase_id,
91
+ phrase_key,
92
+ target_locale,
93
+ value,
94
+ user_id,
95
+ do_xss_check,
96
+ allow_verification)
97
+ ...
98
+ end
99
+
100
+ # good
101
+ def self.create_translation(
102
+ phrase_id,
103
+ phrase_key,
104
+ target_locale,
105
+ value,
106
+ user_id,
107
+ do_xss_check,
108
+ allow_verification
109
+ )
110
+ ...
111
+ end
112
+ ```
113
+
114
+ * <a name="indent-multi-line-bool"></a>Indent succeeding lines in multi-line
115
+ boolean expressions.<sup>[[link](#indent-multi-line-bool)]</sup>
116
+
117
+ ```ruby
118
+ # bad
119
+ def is_eligible?(user)
120
+ Trebuchet.current.launch?(ProgramEligibilityHelper::PROGRAM_TREBUCHET_FLAG) &&
121
+ is_in_program?(user) &&
122
+ program_not_expired
123
+ end
124
+
125
+ # good
126
+ def is_eligible?(user)
127
+ Trebuchet.current.launch?(ProgramEligibilityHelper::PROGRAM_TREBUCHET_FLAG) &&
128
+ is_in_program?(user) &&
129
+ program_not_expired
130
+ end
131
+ ```
132
+
133
+ ### Inline
134
+
135
+ * <a name="trailing-whitespace"></a>Never leave trailing whitespace.
136
+ <sup>[[link](#trailing-whitespace)]</sup>
137
+
138
+ * <a name="space-before-comments"></a>When making inline comments, include a
139
+ space between the end of the code and the start of your comment.
140
+ <sup>[[link](#space-before-comments)]</sup>
141
+
142
+ ```ruby
143
+ # bad
144
+ result = func(a, b)# we might want to change b to c
145
+
146
+ # good
147
+ result = func(a, b) # we might want to change b to c
148
+ ```
149
+
150
+ * <a name="spaces-operators"></a>Use spaces around operators; after commas,
151
+ colons, and semicolons; and around `{` and before `}`.
152
+ <sup>[[link](#spaces-operators)]</sup>
153
+
154
+ ```ruby
155
+ sum = 1 + 2
156
+ a, b = 1, 2
157
+ 1 > 2 ? true : false; puts "Hi"
158
+ [1, 2, 3].each { |e| puts e }
159
+ ```
160
+
161
+ * <a name="no-space-before-commas"></a>Never include a space before a comma.
162
+ <sup>[[link](#no-space-before-commas)]</sup>
163
+
164
+ ```ruby
165
+ result = func(a, b)
166
+ ```
167
+
168
+ * <a name="spaces-block-params"></a>Do not include space inside block
169
+ parameter pipes. Include one space between parameters in a block.
170
+ Include one space outside block parameter pipes.
171
+ <sup>[[link](#spaces-block-params)]</sup>
172
+
173
+ ```ruby
174
+ # bad
175
+ {}.each { | x, y |puts x }
176
+
177
+ # good
178
+ {}.each { |x, y| puts x }
179
+ ```
180
+
181
+ * <a name="no-space-after-!"></a>Do not leave space between `!` and its
182
+ argument.<sup>[[link](#no-space-after-!)]</sup>
183
+
184
+ ```ruby
185
+ !something
186
+ ```
187
+
188
+ * <a name="no-spaces-braces"></a>No spaces after `(`, `[` or before `]`, `)`.
189
+ <sup>[[link](#no-spaces-braces)]</sup>
190
+
191
+ ```ruby
192
+ some(arg).other
193
+ [1, 2, 3].length
194
+ ```
195
+
196
+ * <a name="no-spaces-string-interpolation"></a>Omit whitespace when doing
197
+ string interpolation.<sup>[[link](#no-spaces-string-interpolation)]</sup>
198
+
199
+ ```ruby
200
+ # bad
201
+ var = "This #{ foobar } is interpolated."
202
+
203
+ # good
204
+ var = "This #{foobar} is interpolated."
205
+ ```
206
+
207
+ * <a name="no-spaces-range-literals"></a>Don't use extra whitespace in range
208
+ literals.<sup>[[link](#no-spaces-range-literals)]</sup>
209
+
210
+ ```ruby
211
+ # bad
212
+ (0 ... coll).each do |item|
213
+
214
+ # good
215
+ (0...coll).each do |item|
216
+ ```
217
+
218
+ ### Newlines
219
+
220
+ * <a name="multiline-if-newline"></a>Add a new line after `if` conditions spanning
221
+ multiple lines to help differentiate between the conditions and the body.
222
+ <sup>[[link](#multiline-if-newline)]</sup>
223
+
224
+ ```ruby
225
+ if @reservation_alteration.checkin == @reservation.start_date &&
226
+ @reservation_alteration.checkout == (@reservation.start_date + @reservation.nights)
227
+
228
+ redirect_to_alteration @reservation_alteration
229
+ end
230
+ ```
231
+
232
+ * <a name="newline-after-conditional"></a>Add a new line after conditionals,
233
+ blocks, case statements, etc.<sup>[[link](#newline-after-conditional)]</sup>
234
+
235
+ ```ruby
236
+ if robot.is_awesome?
237
+ send_robot_present
238
+ end
239
+
240
+ robot.add_trait(:human_like_intelligence)
241
+ ```
242
+
243
+ * <a name="newline-different-indent"></a>Don’t include newlines between areas
244
+ of different indentation (such as around class or module bodies).
245
+ <sup>[[link](#newline-different-indent)]</sup>
246
+
247
+ ```ruby
248
+ # bad
249
+ class Foo
250
+
251
+ def bar
252
+ # body omitted
253
+ end
254
+
255
+ end
256
+
257
+ # good
258
+ class Foo
259
+ def bar
260
+ # body omitted
261
+ end
262
+ end
263
+ ```
264
+
265
+ * <a name="newline-between-methods"></a>Include one, but no more than one, new
266
+ line between methods.<sup>[[link](#newline-between-methods)]</sup>
267
+
268
+ ```ruby
269
+ def a
270
+ end
271
+
272
+ def b
273
+ end
274
+ ```
275
+
276
+ * <a name="method-def-empty-lines"></a>Use a single empty line to break between
277
+ statements to break up methods into logical paragraphs internally.
278
+ <sup>[[link](#method-def-empty-lines)]</sup>
279
+
280
+ ```ruby
281
+ def transformorize_car
282
+ car = manufacture(options)
283
+ t = transformer(robot, disguise)
284
+
285
+ car.after_market_mod!
286
+ t.transform(car)
287
+ car.assign_cool_name!
288
+
289
+ fleet.add(car)
290
+ car
291
+ end
292
+ ```
293
+
294
+ * <a name="trailing-newline"></a>End each file with a newline. Don't include
295
+ multiple newlines at the end of a file.
296
+ <sup>[[link](#trailing-newline)]</sup>
297
+
298
+ ## Line Length
299
+
300
+ * Keep each line of code to a readable length. Unless
301
+ you have a reason to, keep lines to fewer than 100 characters.
302
+ ([rationale](./rationales.md#line-length))<sup>
303
+ [[link](#line-length)]</sup>
304
+
305
+ ## Commenting
306
+
307
+ > Though a pain to write, comments are absolutely vital to keeping our code
308
+ > readable. The following rules describe what you should comment and where. But
309
+ > remember: while comments are very important, the best code is
310
+ > self-documenting. Giving sensible names to types and variables is much better
311
+ > than using obscure names that you must then explain through comments.
312
+
313
+ > When writing your comments, write for your audience: the next contributor who
314
+ > will need to understand your code. Be generous — the next one may be you!
315
+
316
+ &mdash;[Google C++ Style Guide][google-c++]
317
+
318
+ Portions of this section borrow heavily from the Google
319
+ [C++][google-c++-comments] and [Python][google-python-comments] style guides.
320
+
321
+ ### Block and inline comments
322
+
323
+ The final place to have comments is in tricky parts of the code. If you're
324
+ going to have to explain it at the next code review, you should comment it now.
325
+ Complicated operations get a few lines of comments before the operations
326
+ commence. Non-obvious ones get comments at the end of the line.
327
+
328
+ ```ruby
329
+ def fallbacks_for(the_locale, opts = {})
330
+ # dup() to produce an array that we can mutate.
331
+ ret = @fallbacks[the_locale].dup
332
+
333
+ # We make two assumptions here:
334
+ # 1) There is only one default locale (that is, it has no less-specific
335
+ # children).
336
+ # 2) The default locale is just a language. (Like :en, and not :"en-US".)
337
+ if opts[:exclude_default] &&
338
+ ret.last == default_locale &&
339
+ ret.last != language_from_locale(the_locale)
340
+ ret.pop
341
+ end
342
+
343
+ ret
344
+ end
345
+ ```
346
+
347
+ On the other hand, never describe the code. Assume the person reading the code
348
+ knows the language (though not what you're trying to do) better than you do.
349
+
350
+ <a name="no-block-comments"></a>Related: do not use block comments. They cannot
351
+ be preceded by whitespace and are not as easy to spot as regular comments.
352
+ <sup>[[link](#no-block-comments)]</sup>
353
+
354
+ ```ruby
355
+ # bad
356
+ =begin
357
+ comment line
358
+ another comment line
359
+ =end
360
+
361
+ # good
362
+ # comment line
363
+ # another comment line
364
+ ```
365
+
366
+ ### Punctuation, spelling and grammar
367
+
368
+ Pay attention to punctuation, spelling, and grammar; it is easier to read
369
+ well-written comments than badly written ones.
370
+
371
+ Comments should be as readable as narrative text, with proper capitalization
372
+ and punctuation. In many cases, complete sentences are more readable than
373
+ sentence fragments. Shorter comments, such as comments at the end of a line of
374
+ code, can sometimes be less formal, but you should be consistent with your
375
+ style.
376
+
377
+ Although it can be frustrating to have a code reviewer point out that you are
378
+ using a comma when you should be using a semicolon, it is very important that
379
+ source code maintain a high level of clarity and readability. Proper
380
+ punctuation, spelling, and grammar help with that goal.
381
+
382
+ ### TODO comments
383
+
384
+ Use TODO comments for code that is temporary, a short-term solution, or
385
+ good-enough but not perfect.
386
+
387
+ TODOs should include the string TODO in all caps, followed by the full name
388
+ of the person who can best provide context about the problem referenced by the
389
+ TODO, in parentheses. A colon is optional. A comment explaining what there is
390
+ to do is required. The main purpose is to have a consistent TODO format that
391
+ can be searched to find the person who can provide more details upon request.
392
+ A TODO is not a commitment that the person referenced will fix the problem.
393
+ Thus when you create a TODO, it is almost always your name that is given.
394
+
395
+ ```ruby
396
+ # bad
397
+ # TODO(RS): Use proper namespacing for this constant.
398
+
399
+ # bad
400
+ # TODO(drumm3rz4lyfe): Use proper namespacing for this constant.
401
+
402
+ # good
403
+ # TODO(Ringo Starr): Use proper namespacing for this constant.
404
+ ```
405
+
406
+ ### Commented-out code
407
+
408
+ * <a name="commented-code"></a>Never leave commented-out code in our codebase.
409
+ <sup>[[link](#commented-code)]</sup>
410
+
411
+ ## Methods
412
+
413
+ ### Method definitions
414
+
415
+ * <a name="method-def-parens"></a>Use `def` with parentheses when there are
416
+ parameters. Omit the parentheses when the method doesn't accept any
417
+ parameters.<sup>[[link](#method-def-parens)]</sup>
418
+
419
+ ```ruby
420
+ def some_method
421
+ # body omitted
422
+ end
423
+
424
+ def some_method_with_parameters(arg1, arg2)
425
+ # body omitted
426
+ end
427
+ ```
428
+
429
+ * <a name="no-default-args"></a>Do not use default positional arguments.
430
+ Use keyword arguments (if available - in Ruby 2.0 or later) or an options
431
+ hash instead.<sup>[[link](#no-default-args)]</sup>
432
+
433
+ ```ruby
434
+ # bad
435
+ def obliterate(things, gently = true, except = [], at = Time.now)
436
+ ...
437
+ end
438
+
439
+ # good
440
+ def obliterate(things, gently: true, except: [], at: Time.now)
441
+ ...
442
+ end
443
+
444
+ # good
445
+ def obliterate(things, options = {})
446
+ options = {
447
+ :gently => true, # obliterate with soft-delete
448
+ :except => [], # skip obliterating these things
449
+ :at => Time.now, # don't obliterate them until later
450
+ }.merge(options)
451
+
452
+ ...
453
+ end
454
+ ```
455
+
456
+ * <a name="no-single-line-methods"></a>Avoid single-line methods. Although
457
+ they are somewhat popular in the wild, there are a few peculiarities about
458
+ their definition syntax that make their use undesirable.
459
+ <sup>[[link](#no-single-line-methods)]</sup>
460
+
461
+ ```ruby
462
+ # bad
463
+ def too_much; something; something_else; end
464
+
465
+ # good
466
+ def some_method
467
+ # body
468
+ end
469
+ ```
470
+
471
+ ### Method calls
472
+
473
+ **Use parentheses** for a method call:
474
+
475
+ * <a name="returns-val-parens"></a>If the method returns a value.
476
+ <sup>[[link](#returns-val-parens)]</sup>
477
+
478
+ ```ruby
479
+ # bad
480
+ @current_user = User.find_by_id 1964192
481
+
482
+ # good
483
+ @current_user = User.find_by_id(1964192)
484
+ ```
485
+
486
+ * <a name="first-arg-parens"></a>If the first argument to the method uses
487
+ parentheses.<sup>[[link](#first-arg-parens)]</sup>
488
+
489
+ ```ruby
490
+ # bad
491
+ put! (x + y) % len, value
492
+
493
+ # good
494
+ put!((x + y) % len, value)
495
+ ```
496
+
497
+ * <a name="space-method-call"></a>Never put a space between a method name and
498
+ the opening parenthesis.<sup>[[link](#space-method-call)]</sup>
499
+
500
+ ```ruby
501
+ # bad
502
+ f (3 + 2) + 1
503
+
504
+ # good
505
+ f(3 + 2) + 1
506
+ ```
507
+
508
+ * <a name="no-args-parens"></a>**Omit parentheses** for a method call if the
509
+ method accepts no arguments.<sup>[[link](#no-args-parens)]</sup>
510
+
511
+ ```ruby
512
+ # bad
513
+ nil?()
514
+
515
+ # good
516
+ nil?
517
+ ```
518
+
519
+ * <a name="no-return-parens"></a>If the method doesn't return a value (or we
520
+ don't care about the return), parentheses are optional. (Especially if the
521
+ arguments overflow to multiple lines, parentheses may add readability.)
522
+ <sup>[[link](#no-return-parens)]</sup>
523
+
524
+ ```ruby
525
+ # okay
526
+ render(:partial => "foo")
527
+
528
+ # okay
529
+ render :partial => "foo"
530
+ ```
531
+
532
+ In either case:
533
+
534
+ * <a name="options-no-braces"></a>If a method accepts an options hash as the
535
+ last argument, do not use `{` `}` during invocation.
536
+ <sup>[[link](#options-no-braces)]</sup>
537
+
538
+ ```ruby
539
+ # bad
540
+ get "/v1/reservations", { :id => 54875 }
541
+
542
+ # good
543
+ get "/v1/reservations", :id => 54875
544
+ ```
545
+
546
+ ## Conditional Expressions
547
+
548
+ ### Conditional keywords
549
+
550
+ * <a name="multiline-if-then"></a>Never use `then` for multi-line `if/unless`.
551
+ <sup>[[link](#multiline-if-then)]</sup>
552
+
553
+ ```ruby
554
+ # bad
555
+ if some_condition then
556
+ ...
557
+ end
558
+
559
+ # good
560
+ if some_condition
561
+ ...
562
+ end
563
+ ```
564
+
565
+ * <a name="multiline-while-until"></a>Never use `do` for multi-line `while` or
566
+ `until`.<sup>[[link](#multiline-while-until)]</sup>
567
+
568
+ ```ruby
569
+ # bad
570
+ while x > 5 do
571
+ ...
572
+ end
573
+
574
+ until x > 5 do
575
+ ...
576
+ end
577
+
578
+ # good
579
+ while x > 5
580
+ ...
581
+ end
582
+
583
+ until x > 5
584
+ ...
585
+ end
586
+ ```
587
+
588
+ * <a name="no-and-or"></a>The `and`, `or`, and `not` keywords are banned. It's
589
+ just not worth it. Always use `&&`, `||`, and `!` instead.
590
+ <sup>[[link](#no-and-or)]</sup>
591
+
592
+ * <a name="only-simple-if-unless"></a>Modifier `if/unless` usage is okay when
593
+ the body is simple, the condition is simple, and the whole thing fits on
594
+ one line. Otherwise, avoid modifier `if/unless`.
595
+ <sup>[[link](#only-simple-if-unless)]</sup>
596
+
597
+ ```ruby
598
+ # bad - this doesn't fit on one line
599
+ add_trebuchet_experiments_on_page(request_opts[:trebuchet_experiments_on_page]) if request_opts[:trebuchet_experiments_on_page] && !request_opts[:trebuchet_experiments_on_page].empty?
600
+
601
+ # okay
602
+ if request_opts[:trebuchet_experiments_on_page] &&
603
+ !request_opts[:trebuchet_experiments_on_page].empty?
604
+
605
+ add_trebuchet_experiments_on_page(request_opts[:trebuchet_experiments_on_page])
606
+ end
607
+
608
+ # bad - this is complex and deserves multiple lines and a comment
609
+ parts[i] = part.to_i(INTEGER_BASE) if !part.nil? && [0, 2, 3].include?(i)
610
+
611
+ # okay
612
+ return if reconciled?
613
+ ```
614
+
615
+ * <a name="no-unless-with-else"></a>Never use `unless` with `else`. Rewrite
616
+ these with the positive case first.<sup>[[link](#no-unless-with-else)]</sup>
617
+
618
+ ```ruby
619
+ # bad
620
+ unless success?
621
+ puts "failure"
622
+ else
623
+ puts "success"
624
+ end
625
+
626
+ # good
627
+ if success?
628
+ puts "success"
629
+ else
630
+ puts "failure"
631
+ end
632
+ ```
633
+
634
+ * <a name="unless-with-multiple-conditions"></a>Avoid `unless` with multiple
635
+ conditions.<sup>[[link](#unless-with-multiple-conditions)]</sup>
636
+
637
+ ```ruby
638
+ # bad
639
+ unless foo? && bar?
640
+ ...
641
+ end
642
+
643
+ # okay
644
+ if !(foo? && bar?)
645
+ ...
646
+ end
647
+ ```
648
+
649
+ * <a name="unless-with-comparison-operator"></a>Avoid `unless` with comparison operators if you can use `if` with an opposing comparison operator.<sup>[[link](#unless-with-comparison-operator)]</sup>
650
+
651
+ ```ruby
652
+ # bad
653
+ unless x == 10
654
+ ...
655
+ end
656
+
657
+ # good
658
+ if x != 10
659
+ ...
660
+ end
661
+
662
+ # bad
663
+ unless x < 10
664
+ ...
665
+ end
666
+
667
+ # good
668
+ if x >= 10
669
+ ...
670
+ end
671
+
672
+ # ok
673
+ unless x === 10
674
+ ...
675
+ end
676
+ ```
677
+
678
+ * <a name="parens-around-conditions"></a>Don't use parentheses around the
679
+ condition of an `if/unless/while`.
680
+ <sup>[[link](#parens-around-conditions)]</sup>
681
+
682
+ ```ruby
683
+ # bad
684
+ if (x > 10)
685
+ ...
686
+ end
687
+
688
+ # good
689
+ if x > 10
690
+ ...
691
+ end
692
+
693
+ ```
694
+
695
+ ### Ternary operator
696
+
697
+ * <a name="avoid-complex-ternary"></a>Avoid the ternary operator (`?:`) except
698
+ in cases where all expressions are extremely trivial. However, do use the
699
+ ternary operator(`?:`) over `if/then/else/end` constructs for single line
700
+ conditionals.<sup>[[link](#avoid-complex-ternary)]</sup>
701
+
702
+ ```ruby
703
+ # bad
704
+ result = if some_condition then something else something_else end
705
+
706
+ # good
707
+ result = some_condition ? something : something_else
708
+ ```
709
+
710
+ * <a name="no-nested-ternaries"></a>Use one expression per branch in a ternary
711
+ operator. This also means that ternary operators must not be nested. Prefer
712
+ `if/else` constructs in these cases.<sup>[[link](#no-nested-ternaries)]</sup>
713
+
714
+ ```ruby
715
+ # bad
716
+ some_condition ? (nested_condition ? nested_something : nested_something_else) : something_else
717
+
718
+ # good
719
+ if some_condition
720
+ nested_condition ? nested_something : nested_something_else
721
+ else
722
+ something_else
723
+ end
724
+ ```
725
+
726
+ * <a name="single-condition-ternary"></a>Avoid multiple conditions in ternaries.
727
+ Ternaries are best used with single conditions.
728
+ <sup>[[link](#single-condition-ternary)]</sup>
729
+
730
+ * <a name="no-multiline-ternaries"></a>Avoid multi-line `?:` (the ternary
731
+ operator), use `if/then/else/end` instead.
732
+ <sup>[[link](#no-multiline-ternaries)]</sup>
733
+
734
+ ```ruby
735
+ # bad
736
+ some_really_long_condition_that_might_make_you_want_to_split_lines ?
737
+ something : something_else
738
+
739
+ # good
740
+ if some_really_long_condition_that_might_make_you_want_to_split_lines
741
+ something
742
+ else
743
+ something_else
744
+ end
745
+ ```
746
+
747
+ ### Nested conditionals
748
+
749
+ * <a name="no-nested-conditionals"></a>
750
+ Avoid the use of nested conditionals for flow of control.
751
+ ([More on this][avoid-else-return-early].) <sup>[[link](#no-nested-conditionals)]</sup>
752
+
753
+ Prefer a guard clause when you can assert invalid data. A guard clause
754
+ is a conditional statement at the top of a function that returns as soon
755
+ as it can.
756
+
757
+ The general principles boil down to:
758
+ * Return immediately once you know your function cannot do anything more.
759
+ * Reduce nesting and indentation in the code by returning early. This makes
760
+ the code easier to read and requires less mental bookkeeping on the part
761
+ of the reader to keep track of `else` branches.
762
+ * The core or most important flows should be the least indented.
763
+
764
+ ```ruby
765
+ # bad
766
+ def compute
767
+ server = find_server
768
+ if server
769
+ client = server.client
770
+ if client
771
+ request = client.make_request
772
+ if request
773
+ process_request(request)
774
+ end
775
+ end
776
+ end
777
+ end
778
+
779
+ # good
780
+ def compute
781
+ server = find_server
782
+ return unless server
783
+ client = server.client
784
+ return unless client
785
+ request = client.make_request
786
+ return unless request
787
+ process_request(request)
788
+ end
789
+ ```
790
+
791
+ Prefer `next` in loops instead of conditional blocks.
792
+
793
+ ```ruby
794
+ # bad
795
+ [0, 1, 2, 3].each do |item|
796
+ if item > 1
797
+ puts item
798
+ end
799
+ end
800
+
801
+ # good
802
+ [0, 1, 2, 3].each do |item|
803
+ next unless item > 1
804
+ puts item
805
+ end
806
+ ```
807
+
808
+ See also the section "Guard Clause", p68-70 in Beck, Kent.
809
+ *Implementation Patterns*. Upper Saddle River: Addison-Wesley, 2008, which
810
+ has inspired some of the content above.
811
+
812
+ ## Syntax
813
+
814
+ * <a name="no-for"></a>Never use `for`, unless you know exactly why. Most of the
815
+ time iterators should be used instead. `for` is implemented in terms of
816
+ `each` (so you're adding a level of indirection), but with a twist - `for`
817
+ doesn't introduce a new scope (unlike `each`) and variables defined in its
818
+ block will be visible outside it.<sup>[[link](#no-for)]</sup>
819
+
820
+ ```ruby
821
+ arr = [1, 2, 3]
822
+
823
+ # bad
824
+ for elem in arr do
825
+ puts elem
826
+ end
827
+
828
+ # good
829
+ arr.each { |elem| puts elem }
830
+ ```
831
+
832
+ * <a name="single-line-blocks"></a>Prefer `{...}` over `do...end` for
833
+ single-line blocks. Avoid using `{...}` for multi-line blocks (multiline
834
+ chaining is always ugly). Always use `do...end` for "control flow" and
835
+ "method definitions" (e.g. in Rakefiles and certain DSLs). Avoid `do...end`
836
+ when chaining.<sup>[[link](#single-line-blocks)]</sup>
837
+
838
+ ```ruby
839
+ names = ["Bozhidar", "Steve", "Sarah"]
840
+
841
+ # good
842
+ names.each { |name| puts name }
843
+
844
+ # bad
845
+ names.each do |name| puts name end
846
+
847
+ # good
848
+ names.each do |name|
849
+ puts name
850
+ puts "yay!"
851
+ end
852
+
853
+ # bad
854
+ names.each { |name|
855
+ puts name
856
+ puts "yay!"
857
+ }
858
+
859
+ # good
860
+ names.select { |name| name.start_with?("S") }.map { |name| name.upcase }
861
+
862
+ # bad
863
+ names.select do |name|
864
+ name.start_with?("S")
865
+ end.map { |name| name.upcase }
866
+ ```
867
+
868
+ Some will argue that multiline chaining would look okay with the use of
869
+ `{...}`, but they should ask themselves if this code is really readable and
870
+ whether the block's content can be extracted into nifty methods.
871
+
872
+ * <a name="self-assignment"></a>Use shorthand self assignment operators
873
+ whenever applicable.<sup>[[link](#self-assignment)]</sup>
874
+
875
+ ```ruby
876
+ # bad
877
+ x = x + y
878
+ x = x * y
879
+ x = x**y
880
+ x = x / y
881
+ x = x || y
882
+ x = x && y
883
+
884
+ # good
885
+ x += y
886
+ x *= y
887
+ x **= y
888
+ x /= y
889
+ x ||= y
890
+ x &&= y
891
+ ```
892
+
893
+ * <a name="semicolons"></a>Avoid semicolons except for in single line class
894
+ definitions. When it is appropriate to use a semicolon, it should be
895
+ directly adjacent to the statement it terminates: there should be no
896
+ space before the semicolon.<sup>[[link](#semicolons)]</sup>
897
+
898
+ ```ruby
899
+ # bad
900
+ puts "foobar"; # superfluous semicolon
901
+ puts "foo"; puts "bar" # two expressions on the same line
902
+
903
+ # good
904
+ puts "foobar"
905
+
906
+ puts "foo"
907
+ puts "bar"
908
+
909
+ puts "foo", "bar" # this applies to puts in particular
910
+ ```
911
+
912
+ * <a name="colon-use"></a>Use :: only to reference constants(this includes
913
+ classes and modules) and constructors (like Array() or Nokogiri::HTML()).
914
+ Do not use :: for regular method invocation.<sup>[[link](#colon-use)]</sup>
915
+
916
+ ```ruby
917
+ # bad
918
+ SomeClass::some_method
919
+ some_object::some_method
920
+
921
+ # good
922
+ SomeClass.some_method
923
+ some_object.some_method
924
+ SomeModule::SomeClass::SOME_CONST
925
+ SomeModule::SomeClass()
926
+ ```
927
+
928
+ * <a name="redundant-return"></a>Avoid `return` where not required.
929
+ <sup>[[link](#redundant-return)]</sup>
930
+
931
+ ```ruby
932
+ # bad
933
+ def some_method(some_arr)
934
+ return some_arr.size
935
+ end
936
+
937
+ # good
938
+ def some_method(some_arr)
939
+ some_arr.size
940
+ end
941
+ ```
942
+
943
+ * <a name="assignment-in-conditionals"></a>Don't use the return value of `=` in
944
+ conditionals<sup>[[link](#assignment-in-conditionals)]</sup>
945
+
946
+ ```ruby
947
+ # bad - shows intended use of assignment
948
+ if (v = array.grep(/foo/))
949
+ ...
950
+ end
951
+
952
+ # bad
953
+ if v = array.grep(/foo/)
954
+ ...
955
+ end
956
+
957
+ # good
958
+ v = array.grep(/foo/)
959
+ if v
960
+ ...
961
+ end
962
+
963
+ ```
964
+
965
+ * <a name="double-pipe-for-uninit"></a>Use `||=` freely to initialize variables.
966
+ <sup>[[link](#double-pipe-for-uninit)]</sup>
967
+
968
+ ```ruby
969
+ # set name to Bozhidar, only if it's nil or false
970
+ name ||= "Bozhidar"
971
+ ```
972
+
973
+ * <a name="no-double-pipes-for-bools"></a>Don't use `||=` to initialize boolean
974
+ variables. (Consider what would happen if the current value happened to be
975
+ `false`.)<sup>[[link](#no-double-pipes-for-bools)]</sup>
976
+
977
+ ```ruby
978
+ # bad - would set enabled to true even if it was false
979
+ enabled ||= true
980
+
981
+ # good
982
+ enabled = true if enabled.nil?
983
+ ```
984
+
985
+ * <a name="lambda-calls"></a>Use `.call` explicitly when calling lambdas.
986
+ <sup>[[link](#lambda-calls)]</sup>
987
+
988
+ ```ruby
989
+ # bad
990
+ lambda.(x, y)
991
+
992
+ # good
993
+ lambda.call(x, y)
994
+ ```
995
+
996
+ * <a name="no-cryptic-perl"></a>Avoid using Perl-style special variables (like
997
+ `$0-9`, `$`, etc. ). They are quite cryptic and their use in anything but
998
+ one-liner scripts is discouraged. Prefer long form versions such as
999
+ `$PROGRAM_NAME`.<sup>[[link](#no-cryptic-perl)]</sup>
1000
+
1001
+ * <a name="single-action-blocks"></a>When a method block takes only one
1002
+ argument, and the body consists solely of reading an attribute or calling
1003
+ one method with no arguments, use the `&:` shorthand.
1004
+ <sup>[[link](#single-action-blocks)]</sup>
1005
+
1006
+ ```ruby
1007
+ # bad
1008
+ bluths.map { |bluth| bluth.occupation }
1009
+ bluths.select { |bluth| bluth.blue_self? }
1010
+
1011
+ # good
1012
+ bluths.map(&:occupation)
1013
+ bluths.select(&:blue_self?)
1014
+ ```
1015
+
1016
+ * <a name="redundant-self"></a>Prefer `some_method` over `self.some_method` when
1017
+ calling a method on the current instance.<sup>[[link](#redundant-self)]</sup>
1018
+
1019
+ ```ruby
1020
+ # bad
1021
+ def end_date
1022
+ self.start_date + self.nights
1023
+ end
1024
+
1025
+ # good
1026
+ def end_date
1027
+ start_date + nights
1028
+ end
1029
+ ```
1030
+
1031
+ In the following three common cases, `self.` is required by the language
1032
+ and is good to use:
1033
+
1034
+ 1. When defining a class method: `def self.some_method`.
1035
+ 2. The *left hand side* when calling an assignment method, including assigning
1036
+ an attribute when `self` is an ActiveRecord model: `self.guest = user`.
1037
+ 3. Referencing the current instance's class: `self.class`.
1038
+
1039
+ * <a name="freeze-constants"></a>When defining an object of any mutable
1040
+ type meant to be a constant, make sure to call `freeze` on it. Common
1041
+ examples are strings, arrays, and hashes.
1042
+ ([More on this][ruby-freeze].)<sup>[[link](#freeze-constants)]</sup>
1043
+
1044
+ The reason is that Ruby constants are actually mutable. Calling `freeze`
1045
+ ensures they are not mutated and are therefore truly constant and
1046
+ attempting to modify them will raise an exception. For strings, this allows
1047
+ older versions of Ruby below 2.2 to intern them.
1048
+
1049
+ ```ruby
1050
+ # bad
1051
+ class Color
1052
+ RED = "red"
1053
+ BLUE = "blue"
1054
+ GREEN = "green"
1055
+
1056
+ ALL_COLORS = [
1057
+ RED,
1058
+ BLUE,
1059
+ GREEN,
1060
+ ]
1061
+
1062
+ COLOR_TO_RGB = {
1063
+ RED => 0xFF0000,
1064
+ BLUE => 0x0000FF,
1065
+ GREEN => 0x00FF00,
1066
+ }
1067
+ end
1068
+
1069
+ # good
1070
+ class Color
1071
+ RED = "red".freeze
1072
+ BLUE = "blue".freeze
1073
+ GREEN = "green".freeze
1074
+
1075
+ ALL_COLORS = [
1076
+ RED,
1077
+ BLUE,
1078
+ GREEN,
1079
+ ].freeze
1080
+
1081
+ COLOR_TO_RGB = {
1082
+ RED => 0xFF0000,
1083
+ BLUE => 0x0000FF,
1084
+ GREEN => 0x00FF00,
1085
+ }.freeze
1086
+ end
1087
+ ```
1088
+
1089
+ ## Naming
1090
+
1091
+ * <a name="snake-case"></a>Use `snake_case` for methods and variables.
1092
+ <sup>[[link](#snake-case)]</sup>
1093
+
1094
+ * <a name="camel-case"></a>Use `CamelCase` for classes and modules. (Keep
1095
+ acronyms like HTTP, RFC, XML uppercase.)
1096
+ <sup>[[link](#camel-case)]</sup>
1097
+
1098
+ * <a name="screaming-snake-case"></a>Use `SCREAMING_SNAKE_CASE` for other
1099
+ constants.<sup>[[link](#screaming-snake-case)]</sup>
1100
+
1101
+ * <a name="predicate-method-names"></a>The names of predicate methods (methods
1102
+ that return a boolean value) should end in a question mark.
1103
+ (i.e. `Array#empty?`).<sup>[[link](#predicate-method-names)]</sup>
1104
+
1105
+ * <a name="bang-methods"></a>The names of potentially "dangerous" methods
1106
+ (i.e. methods that modify `self` or the arguments, `exit!`, etc.) should
1107
+ end with an exclamation mark. Bang methods should only exist if a non-bang
1108
+ method exists. ([More on this][ruby-naming-bang].)
1109
+ <sup>[[link](#bang-methods)]</sup>
1110
+
1111
+ * <a name="throwaway-variables"></a>Name throwaway variables `_`.
1112
+ <sup>[[link](#throwaway-variables)]</sup>
1113
+
1114
+ ```ruby
1115
+ version = "3.2.1"
1116
+ major_version, minor_version, _ = version.split(".")
1117
+ ```
1118
+
1119
+ ## Classes
1120
+
1121
+ * <a name="avoid-class-variables"></a>Avoid the usage of class (`@@`) variables
1122
+ due to their "nasty" behavior in inheritance.
1123
+ <sup>[[link](#avoid-class-variables)]</sup>
1124
+
1125
+ ```ruby
1126
+ class Parent
1127
+ @@class_var = "parent"
1128
+
1129
+ def self.print_class_var
1130
+ puts @@class_var
1131
+ end
1132
+ end
1133
+
1134
+ class Child < Parent
1135
+ @@class_var = "child"
1136
+ end
1137
+
1138
+ Parent.print_class_var # => will print "child"
1139
+ ```
1140
+
1141
+ As you can see all the classes in a class hierarchy actually share one
1142
+ class variable. Class instance variables should usually be preferred
1143
+ over class variables.
1144
+
1145
+ * <a name="singleton-methods"></a>Use `def self.method` to define singleton
1146
+ methods. This makes the methods more resistant to refactoring changes.
1147
+ <sup>[[link](#singleton-methods)]</sup>
1148
+
1149
+ ```ruby
1150
+ class TestClass
1151
+ # bad
1152
+ def TestClass.some_method
1153
+ ...
1154
+ end
1155
+
1156
+ # good
1157
+ def self.some_other_method
1158
+ ...
1159
+ end
1160
+ ```
1161
+ * <a name="no-class-self"></a>Avoid `class << self` except when necessary,
1162
+ e.g. single accessors and aliased attributes.
1163
+ <sup>[[link](#no-class-self)]</sup>
1164
+
1165
+ ```ruby
1166
+ class TestClass
1167
+ # bad
1168
+ class << self
1169
+ def first_method
1170
+ ...
1171
+ end
1172
+
1173
+ def second_method_etc
1174
+ ...
1175
+ end
1176
+ end
1177
+
1178
+ # good
1179
+ class << self
1180
+ attr_accessor :per_page
1181
+ alias_method :nwo, :find_by_name_with_owner
1182
+ end
1183
+
1184
+ def self.first_method
1185
+ ...
1186
+ end
1187
+
1188
+ def self.second_method_etc
1189
+ ...
1190
+ end
1191
+ end
1192
+ ```
1193
+
1194
+ * <a name="access-modifiers"></a>Indent the `public`, `protected`, and
1195
+ `private` methods as much the method definitions they apply to. Leave one
1196
+ blank line above and below them.<sup>[[link](#access-modifiers)]</sup>
1197
+
1198
+ ```ruby
1199
+ class SomeClass
1200
+ def public_method
1201
+ # ...
1202
+ end
1203
+
1204
+ private
1205
+
1206
+ def private_method
1207
+ # ...
1208
+ end
1209
+ end
1210
+ ```
1211
+
1212
+ ## Exceptions
1213
+
1214
+ * <a name="exception-flow-control"></a>Don't use exceptions for flow of control.
1215
+ <sup>[[link](#exception-flow-control)]</sup>
1216
+
1217
+ ```ruby
1218
+ # bad
1219
+ begin
1220
+ n / d
1221
+ rescue ZeroDivisionError
1222
+ puts "Cannot divide by 0!"
1223
+ end
1224
+
1225
+ # good
1226
+ if d.zero?
1227
+ puts "Cannot divide by 0!"
1228
+ else
1229
+ n / d
1230
+ end
1231
+ ```
1232
+
1233
+ * <a name="dont-rescue-exception"></a>Avoid rescuing the `Exception` class.
1234
+ <sup>[[link](#dont-rescue-exception)]</sup>
1235
+
1236
+ ```ruby
1237
+ # bad
1238
+ begin
1239
+ # an exception occurs here
1240
+ rescue Exception
1241
+ # exception handling
1242
+ end
1243
+
1244
+ # good
1245
+ begin
1246
+ # an exception occurs here
1247
+ rescue StandardError
1248
+ # exception handling
1249
+ end
1250
+
1251
+ # acceptable
1252
+ begin
1253
+ # an exception occurs here
1254
+ rescue
1255
+ # exception handling
1256
+ end
1257
+ ```
1258
+
1259
+ * <a name="redundant-exception"></a>Don't specify `RuntimeError` explicitly in
1260
+ the two argument version of raise. Prefer error sub-classes for clarity and
1261
+ explicit error creation.<sup>[[link](#redundant-exception)]</sup>
1262
+
1263
+ ```ruby
1264
+ # bad
1265
+ raise RuntimeError, "message"
1266
+
1267
+ # better - RuntimeError is implicit here
1268
+ raise "message"
1269
+
1270
+ # best
1271
+ class MyExplicitError < RuntimeError; end
1272
+ raise MyExplicitError
1273
+ ```
1274
+
1275
+
1276
+ * <a name="exception-class-messages"></a>
1277
+ Prefer supplying an exception class and a message as two separate arguments
1278
+ to `raise`, instead of an exception instance.
1279
+ <sup>[[link](#exception-class-messages)]</sup>
1280
+
1281
+ ```Ruby
1282
+ # bad
1283
+ raise SomeException.new("message")
1284
+ # Note that there is no way to do `raise SomeException.new("message"), backtrace`.
1285
+
1286
+ # good
1287
+ raise SomeException, "message"
1288
+ # Consistent with `raise SomeException, "message", backtrace`.
1289
+ ```
1290
+
1291
+
1292
+ * <a name="rescue-as-modifier"></a>Avoid using rescue in its modifier form.
1293
+ <sup>[[link](#rescue-as-modifier)]</sup>
1294
+
1295
+ ```ruby
1296
+ # bad
1297
+ read_file rescue handle_error($!)
1298
+
1299
+ # good
1300
+ begin
1301
+ read_file
1302
+ rescue Errno:ENOENT => ex
1303
+ handle_error(ex)
1304
+ end
1305
+ ```
1306
+
1307
+ ## Collections
1308
+
1309
+ * <a name="map-over-collect"></a>Prefer `map` over
1310
+ `collect`.<sup>[[link](#map-over-collect)]</sup>
1311
+
1312
+ * <a name="detect-over-find"></a>Prefer `detect` over `find`. The use of `find`
1313
+ is ambiguous with regard to ActiveRecord's `find` method - `detect` makes
1314
+ clear that you're working with a Ruby collection, not an AR object.
1315
+ <sup>[[link](#detect-over-find)]</sup>
1316
+
1317
+ * <a name="reduce-over-inject"></a>Prefer `reduce` over `inject`.
1318
+ <sup>[[link](#reduce-over-inject)]</sup>
1319
+
1320
+ * <a name="size-over-count"></a>Prefer `size` over either `length` or `count`
1321
+ for performance reasons.<sup>[[link](#size-over-count)]</sup>
1322
+
1323
+ * <a name="empty-collection-literals"></a>Prefer literal array and hash creation
1324
+ notation unless you need to pass parameters to their constructors.
1325
+ <sup>[[link](#empty-collection-literals)]</sup>
1326
+
1327
+ ```ruby
1328
+ # bad
1329
+ arr = Array.new
1330
+ hash = Hash.new
1331
+
1332
+ # good
1333
+ arr = []
1334
+ hash = {}
1335
+
1336
+ # good because constructor requires parameters
1337
+ x = Hash.new { |h, k| h[k] = {} }
1338
+ ```
1339
+
1340
+ * <a name="array-join"></a>Favor `Array#join` over `Array#*` for clarity.
1341
+ <sup>[[link](#array-join)]</sup>
1342
+
1343
+ ```ruby
1344
+ # bad
1345
+ %w(one two three) * ", "
1346
+ # => "one, two, three"
1347
+
1348
+ # good
1349
+ %w(one two three).join(", ")
1350
+ # => "one, two, three"
1351
+ ```
1352
+
1353
+ * <a name="symbol-keys"></a>Use symbols instead of strings as hash keys.
1354
+ <sup>[[link](#symbol-keys)]</sup>
1355
+
1356
+ ```ruby
1357
+ # bad
1358
+ hash = { "one" => 1, "two" => 2, "three" => 3 }
1359
+
1360
+ # good
1361
+ hash = { :one => 1, :two => 2, :three => 3 }
1362
+ ```
1363
+
1364
+ * <a name="symbol-literals"></a>Relatedly, use plain symbols instead of string
1365
+ symbols when possible.<sup>[[link](#symbol-literals)]</sup>
1366
+
1367
+ ```ruby
1368
+ # bad
1369
+ :"symbol"
1370
+
1371
+ # good
1372
+ :symbol
1373
+ ```
1374
+
1375
+ * <a name="deprecated-hash-methods"></a>Use `Hash#key?` instead of
1376
+ `Hash#has_key?` and `Hash#value?` instead of `Hash#has_value?`. According
1377
+ to Matz, the longer forms are considered deprecated.
1378
+ <sup>[[link](#deprecated-hash-methods)]</sup>
1379
+
1380
+ ```ruby
1381
+ # bad
1382
+ hash.has_key?(:test)
1383
+ hash.has_value?(value)
1384
+
1385
+ # good
1386
+ hash.key?(:test)
1387
+ hash.value?(value)
1388
+ ```
1389
+
1390
+ * <a name="multiline-hashes"></a>Use multi-line hashes when it makes the code
1391
+ more readable, and use trailing commas to ensure that parameter changes
1392
+ don't cause extraneous diff lines when the logic has not otherwise changed.
1393
+ <sup>[[link](#multiline-hashes)]</sup>
1394
+
1395
+ ```ruby
1396
+ hash = {
1397
+ :protocol => "https",
1398
+ :only_path => false,
1399
+ :controller => :users,
1400
+ :action => :set_password,
1401
+ :redirect => @redirect_url,
1402
+ :secret => @secret,
1403
+ }
1404
+ ```
1405
+
1406
+ * <a name="array-trailing-comma"></a>Use a trailing comma in an `Array` that
1407
+ spans more than 1 line<sup>[[link](#array-trailing-comma)]</sup>
1408
+
1409
+ ```ruby
1410
+ # good
1411
+ array = [1, 2, 3]
1412
+
1413
+ # good
1414
+ array = [
1415
+ "car",
1416
+ "bear",
1417
+ "plane",
1418
+ "zoo",
1419
+ ]
1420
+ ```
1421
+
1422
+ ## Strings
1423
+
1424
+ * <a name="string-interpolation"></a>Prefer string interpolation instead of
1425
+ string concatenation:<sup>[[link](#string-interpolation)]</sup>
1426
+
1427
+ ```ruby
1428
+ # bad
1429
+ email_with_name = user.name + " <" + user.email + ">"
1430
+
1431
+ # good
1432
+ email_with_name = "#{user.name} <#{user.email}>"
1433
+ ```
1434
+
1435
+ Furthermore, keep in mind Ruby 1.9-style interpolation. Let's say you are
1436
+ composing cache keys like this:
1437
+
1438
+ ```ruby
1439
+ CACHE_KEY = "_store"
1440
+
1441
+ cache.write(@user.id + CACHE_KEY)
1442
+ ```
1443
+
1444
+ Prefer string interpolation instead of string concatenation:
1445
+
1446
+ ```ruby
1447
+ CACHE_KEY = "%d_store"
1448
+
1449
+ cache.write(CACHE_KEY % @user.id)
1450
+ ```
1451
+
1452
+ * <a name="string-concatenation"></a>Avoid using `String#+` when you need to
1453
+ construct large data chunks. Instead, use `String#<<`. Concatenation mutates
1454
+ the string instance in-place and is always faster than `String#+`, which
1455
+ creates a bunch of new string objects.<sup>[[link](#string-concatenation)]</sup>
1456
+
1457
+ ```ruby
1458
+ # good and also fast
1459
+ story = ""
1460
+ story << "The Ugly Duckling"
1461
+
1462
+ paragraphs.each do |paragraph|
1463
+ story << paragraph
1464
+ end
1465
+ ```
1466
+
1467
+ * <a name="multi-line-strings"></a>Use `\` at the end of the line instead of `+`
1468
+ or `<<` to concatenate multi-line strings.
1469
+ <sup>[[link](#multi-line-strings)]</sup>
1470
+
1471
+ ```ruby
1472
+ # bad
1473
+ "Some string is really long and " +
1474
+ "spans multiple lines."
1475
+
1476
+ "Some string is really long and " <<
1477
+ "spans multiple lines."
1478
+
1479
+ # good
1480
+ "Some string is really long and " \
1481
+ "spans multiple lines."
1482
+ ```
1483
+
1484
+ ## Regular Expressions
1485
+
1486
+ * <a name="regex-named-groups"></a>Avoid using `$1-9` as it can be hard to track
1487
+ what they contain. Named groups can be used instead.
1488
+ <sup>[[link](#regex-named-groups)]</sup>
1489
+
1490
+ ```ruby
1491
+ # bad
1492
+ /(regexp)/ =~ string
1493
+ ...
1494
+ process $1
1495
+
1496
+ # good
1497
+ /(?<meaningful_var>regexp)/ =~ string
1498
+ ...
1499
+ process meaningful_var
1500
+ ```
1501
+
1502
+ * <a name="caret-and-dollar-regexp"></a>Be careful with `^` and `$` as they
1503
+ match start/end of line, not string endings. If you want to match the whole
1504
+ string use: `\A` and `\z`.<sup>[[link](#caret-and-dollar-regexp)]</sup>
1505
+
1506
+ ```ruby
1507
+ string = "some injection\nusername"
1508
+ string[/^username$/] # matches
1509
+ string[/\Ausername\z/] # don't match
1510
+ ```
1511
+
1512
+ * <a name="comment-regexes"></a>Use `x` modifier for complex regexps. This makes
1513
+ them more readable and you can add some useful comments. Just be careful as
1514
+ spaces are ignored.<sup>[[link](#comment-regexes)]</sup>
1515
+
1516
+ ```ruby
1517
+ regexp = %r{
1518
+ start # some text
1519
+ \s # white space char
1520
+ (group) # first group
1521
+ (?:alt1|alt2) # some alternation
1522
+ end
1523
+ }x
1524
+ ```
1525
+
1526
+ ## Percent Literals
1527
+
1528
+ * <a name="percent-literal-delimiters"></a>Prefer parentheses over curly
1529
+ braces, brackets, or pipes when using `%`-literal delimiters for
1530
+ consistency, and because the behavior of `%`-literals is closer to method
1531
+ calls than the alternatives.<sup>[[link](#percent-literal-delimiters)]</sup>
1532
+
1533
+ ```ruby
1534
+ # bad
1535
+ %w[date locale]
1536
+ %w{date locale}
1537
+ %w|date locale|
1538
+
1539
+ # good
1540
+ %w(date locale)
1541
+ ```
1542
+
1543
+ * <a name="percent-w"></a>Use `%w` freely.<sup>[[link](#percent-w)]</sup>
1544
+
1545
+ ```ruby
1546
+ STATES = %w(draft open closed)
1547
+ ```
1548
+
1549
+ * <a name="percent-parens"></a>Use `%()` for single-line strings which require
1550
+ both interpolation and embedded double-quotes. For multi-line strings,
1551
+ prefer heredocs.<sup>[[link](#percent-parens)]</sup>
1552
+
1553
+ ```ruby
1554
+ # bad - no interpolation needed
1555
+ %(Welcome, Jane!)
1556
+ # should be "Welcome, Jane!"
1557
+
1558
+ # bad - no double-quotes
1559
+ %(This is #{quality} style)
1560
+ # should be "This is #{quality} style"
1561
+
1562
+ # bad - multiple lines
1563
+ %(Welcome, Jane!\nPlease enjoy your stay at #{location}\nCheers!)
1564
+ # should be a heredoc.
1565
+
1566
+ # good - requires interpolation, has quotes, single line
1567
+ %(Welcome, #{name}!)
1568
+ ```
1569
+
1570
+ * <a name="percent-r"></a>Use `%r` only for regular expressions matching *more
1571
+ than* one "/" character.<sup>[[link](#percent-r)]</sup>
1572
+
1573
+ ```ruby
1574
+ # bad
1575
+ %r(\s+)
1576
+
1577
+ # still bad
1578
+ %r(^/(.*)$)
1579
+ # should be /^\/(.*)$/
1580
+
1581
+ # good
1582
+ %r(^/blog/2011/(.*)$)
1583
+ ```
1584
+
1585
+ * <a name="percent-x"></a>Avoid the use of %x unless you're going to invoke a
1586
+ command with backquotes in it (which is rather unlikely).
1587
+ <sup>[[link](#percent-x)]</sup>
1588
+
1589
+ ```ruby
1590
+ # bad
1591
+ date = %x(date)
1592
+
1593
+ # good
1594
+ date = `date`
1595
+ echo = %x(echo `date`)
1596
+ ```
1597
+
1598
+ ## Rails
1599
+
1600
+ * <a name="next-line-return"></a>When immediately returning after calling
1601
+ `render` or `redirect_to`, put `return` on the next line, not the same line.
1602
+ <sup>[[link](#next-line-return)]</sup>
1603
+
1604
+ ```ruby
1605
+ # bad
1606
+ render :text => "Howdy" and return
1607
+
1608
+ # good
1609
+ render :text => "Howdy"
1610
+ return
1611
+
1612
+ # still bad
1613
+ render :text => "Howdy" and return if foo.present?
1614
+
1615
+ # good
1616
+ if foo.present?
1617
+ render :text => "Howdy"
1618
+ return
1619
+ end
1620
+ ```
1621
+
1622
+ ### Scopes
1623
+ * <a name="scope-lambda"></a>When defining ActiveRecord model scopes, wrap the
1624
+ relation in a `lambda`. A naked relation forces a database connection to be
1625
+ established at class load time (instance startup).
1626
+ <sup>[[link](#scope-lambda)]</sup>
1627
+
1628
+ ```ruby
1629
+ # bad
1630
+ scope :foo, where(:bar => 1)
1631
+
1632
+ # good
1633
+ scope :foo, -> { where(:bar => 1) }
1634
+ ```
1635
+
1636
+ ## Be Consistent
1637
+
1638
+ > If you're editing code, take a few minutes to look at the code around you and
1639
+ > determine its style. If they use spaces around all their arithmetic
1640
+ > operators, you should too. If their comments have little boxes of hash marks
1641
+ > around them, make your comments have little boxes of hash marks around them
1642
+ > too.
1643
+
1644
+ > The point of having style guidelines is to have a common vocabulary of coding
1645
+ > so people can concentrate on what you're saying rather than on how you're
1646
+ > saying it. We present global style rules here so people know the vocabulary,
1647
+ > but local style is also important. If code you add to a file looks
1648
+ > drastically different from the existing code around it, it throws readers out
1649
+ > of their rhythm when they go to read it. Avoid this.
1650
+
1651
+ &mdash; [Google C++ Style Guide][google-c++]
1652
+
1653
+ [rubocop-guide]: https://github.com/rubocop-hq/ruby-style-guide
1654
+ [github-ruby]: https://github.com/styleguide/ruby
1655
+ [google-c++]: https://google.github.io/styleguide/cppguide.html
1656
+ [google-c++-comments]: https://google.github.io/styleguide/cppguide.html#Comments
1657
+ [google-python-comments]: https://google.github.io/styleguide/pyguide.html#Comments
1658
+ [ruby-naming-bang]: http://dablog.rubypal.com/2007/8/15/bang-methods-or-danger-will-rubyist
1659
+ [ruby-freeze]: https://blog.honeybadger.io/when-to-use-freeze-and-frozen-in-ruby/
1660
+ [avoid-else-return-early]: http://blog.timoxley.com/post/47041269194/avoid-else-return-early