rubocop-shopify 2.14.0 → 2.15.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,1418 @@
1
+ ---
2
+ layout: base
3
+ title: Ruby Style Guide
4
+ permalink: '/'
5
+ ---
6
+
7
+ # Ruby Style Guide
8
+
9
+ Ruby is the main language at Shopify. We are primarily a Ruby shop and we are
10
+ probably one of the largest out there. Ruby is the go-to language for new web
11
+ projects and scripting.
12
+
13
+ We expect all developers at Shopify to have at least a passing understanding of
14
+ Ruby. It's a great language. It will make you a better developer no matter what
15
+ you work in day to day. What follows is a loose coding style to follow while
16
+ developing in Ruby.
17
+
18
+ This Style Guide is the result of over a decade of Ruby development at Shopify.
19
+ Much of its content is based on Bozhidar Batsov's [Ruby Style
20
+ Guide](https://github.com/rubocop-hq/ruby-style-guide), adapted to Shopify by
21
+ [many
22
+ contributors](https://github.com/Shopify/ruby-style-guide/graphs/contributors).
23
+
24
+ ### Adoption with RuboCop
25
+
26
+ We recommend using [RuboCop](https://github.com/rubocop-hq/rubocop) in your Ruby
27
+ projects to help you adopt this Style Guide. To know how to install and use
28
+ RuboCop please refer to [RuboCop's official
29
+ documentation](https://docs.rubocop.org/rubocop/).
30
+
31
+ We offer a default RuboCop configuration you can inherit from and be in sync
32
+ with this Style Guide. To use it, you can add this to your `Gemfile`:
33
+
34
+ ~~~ruby
35
+ gem "rubocop-shopify", require: false
36
+ ~~~
37
+
38
+ And add to the top of your project's RuboCop configuration file:
39
+
40
+ ~~~yml
41
+ inherit_gem:
42
+ rubocop-shopify: rubocop.yml
43
+ ~~~
44
+
45
+ Any `Include` or `Exclude` configuration provided will be merged with RuboCop's defaults.
46
+
47
+ For more information about inheriting configuration from a gem please check
48
+ [RuboCop's
49
+ documentation](https://docs.rubocop.org/rubocop/configuration.html#inheriting-configuration-from-a-dependency-gem).
50
+
51
+ ## Table of Contents
52
+
53
+ * [General](#general)
54
+ * [Layout](#layout)
55
+ * [Syntax](#syntax)
56
+ * [Naming](#naming)
57
+ * [Classes and Modules](#classes-and-modules)
58
+ * [Exceptions](#exceptions)
59
+ * [Collections](#collections)
60
+ * [Strings](#strings)
61
+ * [Regular Expressions](#regular-expressions)
62
+ * [Percent Literals](#percent-literals)
63
+ * [Testing](#testing)
64
+
65
+ ## General
66
+
67
+ * Make all lines of your methods operate on the same level of abstraction.
68
+ (Single Level of Abstraction Principle)
69
+
70
+ * Code in a functional way. Avoid mutation (side effects) when you can.
71
+
72
+ * [Avoid defensive programming](https://web.archive.org/web/20211013164839/http://www.erlang.se/doc/programming_rules.shtml#HDR11)
73
+ > Overly defensive programming may safeguard against errors that will never be encountered, thus incurring run-time and maintenance costs.
74
+
75
+ * Avoid mutating arguments.
76
+
77
+ * Avoid monkeypatching.
78
+
79
+ * Avoid long methods.
80
+
81
+ * Avoid long parameter lists.
82
+
83
+ * Avoid needless metaprogramming.
84
+
85
+ * Prefer `public_send` over `send` so as not to circumvent `private`/`protected`
86
+ visibility.
87
+
88
+ * Write `ruby -w` safe code.
89
+
90
+ * Avoid more than three levels of block nesting.
91
+
92
+ ## Layout
93
+
94
+ * Use `UTF-8` as the source file encoding.
95
+
96
+ * Use 2 space indent, no tabs.
97
+
98
+ * Use Unix-style line endings.
99
+
100
+ * Avoid using `;` to separate statements and expressions. Use one
101
+ expression per line.
102
+
103
+ * Use spaces around operators, after commas, colons and semicolons, around `{`
104
+ and before `}`.
105
+
106
+ * Avoid spaces after `(`, `[` and before `]`, `)`.
107
+
108
+ * Avoid space after the `!` operator.
109
+
110
+ * Avoid space inside range literals.
111
+
112
+ * Avoid space around method call operators.
113
+
114
+ ~~~ruby
115
+ # bad
116
+ foo . bar
117
+
118
+ # good
119
+ foo.bar
120
+ ~~~
121
+
122
+ * Avoid space in lambda literals.
123
+
124
+ ~~~ruby
125
+ # bad
126
+ a = -> (x, y) { x + y }
127
+
128
+ # good
129
+ a = ->(x, y) { x + y }
130
+ ~~~
131
+
132
+ * Indent `when` as deep as the `case` line.
133
+
134
+ * When assigning the result of a conditional expression to a variable, align its
135
+ branches with the variable that receives the return value.
136
+
137
+ ~~~ ruby
138
+ # bad
139
+ result =
140
+ if some_cond
141
+ # ...
142
+ # ...
143
+ calc_something
144
+ else
145
+ calc_something_else
146
+ end
147
+
148
+ # good
149
+ result = if some_cond
150
+ # ...
151
+ # ...
152
+ calc_something
153
+ else
154
+ calc_something_else
155
+ end
156
+ ~~~
157
+
158
+ * When assigning the result of a begin block, align rescue/ensure/end with the start of the line
159
+
160
+ ~~~ ruby
161
+ # bad
162
+ host = begin
163
+ URI.parse(value).host
164
+ rescue URI::Error
165
+ nil
166
+ end
167
+
168
+ # good
169
+ host = begin
170
+ URI.parse(value).host
171
+ rescue URI::Error
172
+ nil
173
+ end
174
+ ~~~
175
+
176
+ * Use empty lines between method definitions and also to break up methods into
177
+ logical paragraphs internally.
178
+
179
+ * Use spaces around the `=` operator when assigning default values to method
180
+ parameters.
181
+
182
+ * Avoid line continuation `\` where not required.
183
+
184
+ * Align the parameters of a method call, if they span more than one line, with
185
+ one level of indentation relative to the start of the line with the method
186
+ call.
187
+
188
+ ~~~ ruby
189
+ # starting point (line is too long)
190
+ def send_mail(source)
191
+ Mailer.deliver(to: "bob@example.com", from: "us@example.com", subject: "Important message", body: source.text)
192
+ end
193
+
194
+ # bad (double indent)
195
+ def send_mail(source)
196
+ Mailer.deliver(
197
+ to: "bob@example.com",
198
+ from: "us@example.com",
199
+ subject: "Important message",
200
+ body: source.text)
201
+ end
202
+
203
+ # good
204
+ def send_mail(source)
205
+ Mailer.deliver(
206
+ to: "bob@example.com",
207
+ from: "us@example.com",
208
+ subject: "Important message",
209
+ body: source.text,
210
+ )
211
+ end
212
+ ~~~
213
+
214
+ * When chaining methods on multiple lines, indent successive calls by one level
215
+ of indentation.
216
+
217
+ ~~~ ruby
218
+ # bad (indented to the previous call)
219
+ User.pluck(:name)
220
+ .sort(&:casecmp)
221
+ .chunk { |n| n[0] }
222
+
223
+ # good
224
+ User
225
+ .pluck(:name)
226
+ .sort(&:casecmp)
227
+ .chunk { |n| n[0] }
228
+ ~~~
229
+
230
+ * Align the elements of array literals spanning multiple lines.
231
+
232
+ * Limit lines to 120 characters.
233
+
234
+ * Avoid trailing whitespace.
235
+
236
+ * Avoid extra whitespace, except for alignment purposes.
237
+
238
+ * End each file with a newline.
239
+
240
+ * Avoid block comments:
241
+
242
+ ~~~ ruby
243
+ # bad
244
+ =begin
245
+ comment line
246
+ another comment line
247
+ =end
248
+
249
+ # good
250
+ # comment line
251
+ # another comment line
252
+ ~~~
253
+
254
+ * Place the closing method call brace on the line after the last argument when
255
+ opening brace is on a separate line from the first argument.
256
+
257
+ ~~~ ruby
258
+ # bad
259
+ method(
260
+ arg_1,
261
+ arg_2)
262
+
263
+ # good
264
+ method(
265
+ arg_1,
266
+ arg_2,
267
+ )
268
+ ~~~
269
+
270
+ * Place each element/argument on a new line when wrapping a method call, hash, or array
271
+ on multiple lines.
272
+
273
+ ~~~ ruby
274
+ # bad
275
+
276
+ method(arg_1, arg_2,
277
+ arg_3
278
+ )
279
+
280
+ [
281
+ value_1, value_2,
282
+ value_3,
283
+ ]
284
+
285
+ {
286
+ key1: value_1,
287
+ key2: value_2, key3: value_3,
288
+ }
289
+
290
+ # good
291
+
292
+ method(
293
+ arg_1,
294
+ arg_2,
295
+ arg_3,
296
+ )
297
+
298
+ [
299
+ value_1,
300
+ value_2,
301
+ value_3,
302
+ ]
303
+
304
+ {
305
+ key1: value_1,
306
+ key2: value_2,
307
+ key3: value_3,
308
+ }
309
+
310
+ # good (special cases)
311
+
312
+ # Single argument method call
313
+ method({
314
+ foo: bar,
315
+ })
316
+
317
+ # Last argument, itself is multiline
318
+ class User
319
+ after_save :method, if: -> {
320
+ do_some_checks
321
+ }
322
+ end
323
+
324
+ # Single value array
325
+ errors = [{
326
+ error_code: 1234,
327
+ error_message: "This is an error",
328
+ }]
329
+
330
+ ~~~
331
+
332
+ * Separate magic comments from code and documentation with a blank line.
333
+
334
+ ~~~ruby
335
+ # good
336
+ # frozen_string_literal: true
337
+
338
+ # Some documentation for Person
339
+ class Person
340
+ # Some code
341
+ end
342
+
343
+ # bad
344
+ # frozen_string_literal: true
345
+ # Some documentation for Person
346
+ class Person
347
+ # Some code
348
+ end
349
+ ~~~
350
+
351
+ * Use empty lines around attribute accessor.
352
+
353
+ ~~~ruby
354
+ # bad
355
+ class Foo
356
+ attr_reader :foo
357
+ def foo
358
+ # do something...
359
+ end
360
+ end
361
+
362
+ # good
363
+ class Foo
364
+ attr_reader :foo
365
+
366
+ def foo
367
+ # do something...
368
+ end
369
+ end
370
+ ~~~
371
+
372
+ * Avoid empty lines around method, class, module, and block bodies.
373
+
374
+ ~~~ruby
375
+ # bad
376
+ class Foo
377
+
378
+ def foo
379
+
380
+ begin
381
+
382
+ do_something do
383
+
384
+ something
385
+
386
+ end
387
+
388
+ rescue
389
+
390
+ something
391
+
392
+ end
393
+
394
+ true
395
+
396
+ end
397
+
398
+ end
399
+
400
+ # good
401
+ class Foo
402
+ def foo
403
+ begin
404
+ do_something do
405
+ something
406
+ end
407
+ rescue
408
+ something
409
+ end
410
+ end
411
+ end
412
+ ~~~
413
+
414
+ ## Syntax
415
+
416
+ * Use `::` only to reference constants (this includes classes and modules) and
417
+ constructors (like `Array()` or `Nokogiri::HTML()`). Avoid `::` for
418
+ regular method invocation.
419
+
420
+ * Avoid using `::` for defining class and modules, or for inheritance, since
421
+ constant lookup will not search in parent classes/modules.
422
+
423
+ ~~~ ruby
424
+ # bad
425
+ module A
426
+ FOO = "test"
427
+ end
428
+
429
+ class A::B
430
+ puts FOO # this will raise a NameError exception
431
+ end
432
+
433
+ # good
434
+ module A
435
+ FOO = "test"
436
+
437
+ class B
438
+ puts FOO
439
+ end
440
+ end
441
+ ~~~
442
+
443
+ * Use def with parentheses when there are parameters. Omit the parentheses when
444
+ the method doesn't accept any parameters.
445
+
446
+ * Avoid `for`.
447
+
448
+ * Avoid `then`.
449
+
450
+ * Favour the ternary operator(`?:`) over `if/then/else/end` constructs.
451
+
452
+ ~~~ ruby
453
+ # bad
454
+ result = if some_condition then something else something_else end
455
+
456
+ # good
457
+ result = some_condition ? something : something_else
458
+ ~~~
459
+
460
+ * Use one expression per branch in a ternary operator. This also means that
461
+ ternary operators must not be nested. Prefer if/else constructs in these
462
+ cases.
463
+
464
+ * Avoid multiline `?:` (the ternary operator); use `if/unless` instead.
465
+
466
+ * Use `when x then ...` for one-line cases.
467
+
468
+ * Use `!` instead of `not`.
469
+
470
+ * Prefer `&&`/`||` over `and`/`or`.
471
+
472
+ * Favour `unless` over `if` for negative conditions.
473
+
474
+ * Avoid `unless` with `else`. Rewrite these with the positive case first.
475
+
476
+ * Use parentheses around the arguments of method invocations. Omit parentheses
477
+ when not providing arguments. Also omit parentheses when the invocation is
478
+ single-line and the method:
479
+ - is a class method call with implicit receiver.
480
+ - is called by syntactic sugar (e.g: `1 + 1` calls the `+` method, `foo[bar]`
481
+ calls the `[]` method, etc).
482
+
483
+ ~~~ ruby
484
+ # bad
485
+ class User
486
+ include(Bar)
487
+ has_many(:posts)
488
+ end
489
+
490
+ # good
491
+ class User
492
+ include Bar
493
+ has_many :posts
494
+ SomeClass.some_method(:foo)
495
+ end
496
+ ~~~
497
+
498
+ - is one of the following methods:
499
+ * `require`
500
+ * `require_relative`
501
+ * `require_dependency`
502
+ * `yield`
503
+ * `raise`
504
+ * `puts`
505
+
506
+ * Omit the outer braces around an implicit options hash.
507
+
508
+ * Use the proc invocation shorthand when the invoked method is the only
509
+ operation of a block.
510
+
511
+ ~~~ ruby
512
+ # bad
513
+ names.map { |name| name.upcase }
514
+
515
+ # good
516
+ names.map(&:upcase)
517
+ ~~~
518
+
519
+ * Prefer `{...}` over `do...end` for single-line blocks.
520
+
521
+ * Prefer `do..end` over `{...}` for multi-line blocks.
522
+
523
+ * Omit `return` where possible.
524
+
525
+ * Omit `self` where possible.
526
+
527
+ ~~~ ruby
528
+ # bad
529
+ self.my_method
530
+
531
+ # good
532
+ my_method
533
+
534
+ # also good
535
+ attr_writer :name
536
+
537
+ def my_method
538
+ self.name = "Rafael" # `self` is needed to reference the attribute writer.
539
+ end
540
+ ~~~
541
+
542
+ * Wrap assignment in parentheses when using its return value in a conditional
543
+ statement.
544
+
545
+ ~~~ ruby
546
+ if (value = /foo/.match(string))
547
+ ~~~
548
+
549
+ * Use `||=` to initialize variables only if they're not already initialized.
550
+
551
+ * Avoid using `||=` to initialize boolean variables.
552
+
553
+ ~~~ ruby
554
+ # bad - would set enabled to true even if it was false
555
+ @enabled ||= true
556
+
557
+ # good
558
+ @enabled = true if @enabled.nil?
559
+
560
+ # also valid - defined? workaround
561
+ @enabled = true unless defined?(@enabled)
562
+ ~~~
563
+
564
+ * Avoid spaces between a method name and the opening parenthesis.
565
+
566
+ * Prefer the lambda literal syntax over `lambda`.
567
+
568
+ ~~~ ruby
569
+ # bad
570
+ l = lambda { |a, b| a + b }
571
+ l.call(1, 2)
572
+
573
+ l = lambda do |a, b|
574
+ tmp = a * 7
575
+ tmp * b / 50
576
+ end
577
+
578
+ # good
579
+ l = ->(a, b) { a + b }
580
+ l.call(1, 2)
581
+
582
+ l = ->(a, b) do
583
+ tmp = a * 7
584
+ tmp * b / 50
585
+ end
586
+ ~~~
587
+
588
+ * Prefer `proc` over `Proc.new`.
589
+
590
+ * Prefix unused block parameters with `_`. It's also acceptable to use just `_`.
591
+
592
+ * Prefer a guard clause when you can assert invalid data. A guard clause is a
593
+ conditional statement at the top of a function that bails out as soon as it
594
+ can.
595
+
596
+ ~~~ ruby
597
+ # bad
598
+ def compute_thing(thing)
599
+ if thing[:foo]
600
+ update_with_bar(thing)
601
+ if thing[:foo][:bar]
602
+ partial_compute(thing)
603
+ else
604
+ re_compute(thing)
605
+ end
606
+ end
607
+ end
608
+
609
+ # good
610
+ def compute_thing(thing)
611
+ return unless thing[:foo]
612
+ update_with_bar(thing[:foo])
613
+ return re_compute(thing) unless thing[:foo][:bar]
614
+ partial_compute(thing)
615
+ end
616
+ ~~~
617
+
618
+ * Prefer keyword arguments over options hash.
619
+
620
+ * Prefer `map` over `collect`, `find` over `detect`, `select` over `find_all`,
621
+ `size` over `length`.
622
+
623
+ * Prefer `Time` over `DateTime`.
624
+
625
+ * Prefer `Time.iso8601(foo)` instead of `Time.parse(foo)` when expecting ISO8601
626
+ formatted time strings like `"2018-03-20T11:16:39-04:00"`.
627
+
628
+ * Avoid returning from a `begin` block in assignment contexts. If you return
629
+ from a method inside a `begin` block, the return will prevent the assignment
630
+ from taking place, potentially causing confusing memoization bugs.
631
+
632
+ ~~~ ruby
633
+ # bad
634
+ def foo
635
+ @foo ||= begin
636
+ return 1 if flag?
637
+ 2
638
+ end
639
+ end
640
+
641
+ # good
642
+ def foo
643
+ @foo ||= begin
644
+ if flag?
645
+ 1
646
+ else
647
+ 2
648
+ end
649
+ end
650
+ end
651
+ ~~~
652
+
653
+ ## Naming
654
+
655
+ * Use `snake_case` for symbols, methods, and variables.
656
+
657
+ * Use `CamelCase` for classes and modules, but keep acronyms like HTTP, RFC, XML
658
+ uppercase.
659
+
660
+ * Use `snake_case` for naming files and directories, e.g. `hello_world.rb`.
661
+
662
+ * Define a single class or module per source file. Name the file name as the
663
+ class or module, but replacing `CamelCase` with `snake_case`.
664
+
665
+ * Use `SCREAMING_SNAKE_CASE` for other constants.
666
+
667
+ * When using inject with short blocks, name the arguments according to what is
668
+ being injected, e.g. `|hash, e|` (mnemonic: hash, element)
669
+
670
+ * When defining binary operators, name the parameter `other`(`<<` and `[]` are
671
+ exceptions to the rule, since their semantics are different).
672
+
673
+ * Name predicate methods with a `?`. Predicate methods are methods that return a
674
+ boolean value.
675
+
676
+ * Avoid ending method names with a `?` if they don't return a boolean.
677
+
678
+ * Avoid prefixing method names with `is_`.
679
+
680
+ ~~~ruby
681
+ # bad
682
+ def is_empty?
683
+ end
684
+
685
+ # good
686
+ def empty?
687
+ end
688
+ ~~~
689
+
690
+ * Avoid starting method names with `get_`.
691
+
692
+ * Avoid ending method names with `!` when there is no equivalent method without
693
+ the bang. Bangs are to mark a more dangerous version of a method, e.g. `save`
694
+ returns a boolean in ActiveRecord, whereas `save!` will throw an exception on
695
+ failure.
696
+
697
+ * Avoid magic numbers. Use a constant and give it a meaningful name.
698
+
699
+ * Avoid nomenclature that has (or could be interpreted to have) discriminatory
700
+ origins.
701
+
702
+ ## Comments
703
+
704
+ * Include relevant context in comments, as readers might be missing it.
705
+
706
+ * Keep comments in sync with code.
707
+
708
+ * Write comments using proper capitalization and punctuation.
709
+
710
+ * Avoid superfluous comments. Focus on **why** the code is the way it is if
711
+ this is not obvious, not **how** the code works.
712
+
713
+ ## Classes and Modules
714
+
715
+ * Prefer modules to classes with only class methods. Classes should be used only
716
+ when it makes sense to create instances out of them.
717
+
718
+ * Prefer `extend self` over `module_function`.
719
+
720
+ ~~~ ruby
721
+ # bad
722
+ module SomeModule
723
+ module_function
724
+
725
+ def some_method
726
+ end
727
+
728
+ def some_other_method
729
+ end
730
+ end
731
+
732
+ # good
733
+ module SomeModule
734
+ extend self
735
+
736
+ def some_method
737
+ end
738
+
739
+ def some_other_method
740
+ end
741
+ end
742
+ ~~~
743
+
744
+ * Use a `class << self` block over `def self.` when defining class methods, and
745
+ group them together within a single block.
746
+
747
+ ~~~ ruby
748
+ # bad
749
+ class SomeClass
750
+ def self.method1
751
+ end
752
+
753
+ def method2
754
+ end
755
+
756
+ private
757
+
758
+ def method3
759
+ end
760
+
761
+ def self.method4 # this is actually not private
762
+ end
763
+ end
764
+
765
+ # good
766
+ class SomeClass
767
+ class << self
768
+ def method1
769
+ end
770
+
771
+ private
772
+
773
+ def method4
774
+ end
775
+ end
776
+
777
+ def method2
778
+ end
779
+
780
+ private
781
+
782
+ def method3
783
+ end
784
+ end
785
+ ~~~
786
+
787
+ * Respect the [Liskov Substitution Principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle)
788
+ when designing class hierarchies.
789
+
790
+ * Use `attr_accessor`, `attr_reader`, and `attr_writer` to define trivial
791
+ accessors and mutators.
792
+
793
+ ~~~ ruby
794
+ # bad
795
+ class Person
796
+ def initialize(first_name, last_name)
797
+ @first_name = first_name
798
+ @last_name = last_name
799
+ end
800
+
801
+ def first_name
802
+ @first_name
803
+ end
804
+
805
+ def last_name
806
+ @last_name
807
+ end
808
+ end
809
+
810
+ # good
811
+ class Person
812
+ attr_reader :first_name, :last_name
813
+
814
+ def initialize(first_name, last_name)
815
+ @first_name = first_name
816
+ @last_name = last_name
817
+ end
818
+ end
819
+ ~~~
820
+
821
+ * Prefer `attr_reader` and `attr_accessor` over `attr`.
822
+
823
+ * Avoid class (`@@`) variables.
824
+
825
+ * Indent the `public`, `protected`, and `private` methods as much as the method
826
+ definitions they apply to. Leave one blank line above the visibility modifier
827
+ and one blank line below it.
828
+
829
+ ~~~ ruby
830
+ class SomeClass
831
+ def public_method
832
+ # ...
833
+ end
834
+
835
+ private
836
+
837
+ def private_method
838
+ # ...
839
+ end
840
+
841
+ def another_private_method
842
+ # ...
843
+ end
844
+ end
845
+ ~~~
846
+
847
+ * Prefer `alias_method` over `alias`.
848
+
849
+ ## Exceptions
850
+
851
+ * Signal exceptions using the `raise` method.
852
+
853
+ * Omit `RuntimeError` in the two argument version of `raise`.
854
+
855
+ ~~~ ruby
856
+ # bad
857
+ raise RuntimeError, "message"
858
+
859
+ # good - signals a RuntimeError by default
860
+ raise "message"
861
+ ~~~
862
+
863
+ * Prefer supplying an exception class and a message as two separate arguments to
864
+ `raise` instead of an exception instance.
865
+
866
+ ~~~ ruby
867
+ # bad
868
+ raise SomeException.new("message")
869
+ # Note that there is no way to do `raise SomeException.new("message"), backtrace`.
870
+
871
+ # good
872
+ raise SomeException, "message"
873
+ # Consistent with `raise SomeException, "message", backtrace`.
874
+ ~~~
875
+
876
+ * Avoid returning from an `ensure` block. If you explicitly return from a method
877
+ inside an `ensure` block, the return will take precedence over any exception
878
+ being raised, and the method will return as if no exception had been raised at
879
+ all. In effect, the exception will be silently thrown away.
880
+
881
+ ~~~ ruby
882
+ # bad
883
+ def foo
884
+ raise
885
+ ensure
886
+ return "very bad idea"
887
+ end
888
+ ~~~
889
+
890
+ * Use implicit begin blocks where possible.
891
+
892
+ ~~~ ruby
893
+ # bad
894
+ def foo
895
+ begin
896
+ # main logic goes here
897
+ rescue
898
+ # failure handling goes here
899
+ end
900
+ end
901
+
902
+ # good
903
+ def foo
904
+ # main logic goes here
905
+ rescue
906
+ # failure handling goes here
907
+ end
908
+ ~~~
909
+
910
+ * Avoid empty `rescue` statements.
911
+
912
+ ~~~ ruby
913
+ # bad
914
+ begin
915
+ # an exception occurs here
916
+ rescue SomeError
917
+ # the rescue clause does absolutely nothing
918
+ end
919
+
920
+ # bad - `rescue nil` swallows all errors, including syntax errors, and
921
+ # makes them hard to track down.
922
+ do_something rescue nil
923
+ ~~~
924
+
925
+ * Avoid `rescue` in its modifier form.
926
+
927
+ ~~~ ruby
928
+ # bad - this catches exceptions of StandardError class and its descendant
929
+ # classes.
930
+ read_file rescue handle_error($!)
931
+
932
+ # good - this catches only the exceptions of Errno::ENOENT class and its
933
+ # descendant classes.
934
+ def foo
935
+ read_file
936
+ rescue Errno::ENOENT => error
937
+ handle_error(error)
938
+ end
939
+ ~~~
940
+
941
+ * Avoid rescuing the `Exception` class.
942
+
943
+ ~~~ ruby
944
+ # bad
945
+ begin
946
+ # calls to exit and kill signals will be caught (except kill -9)
947
+ exit
948
+ rescue Exception
949
+ puts "you didn't really want to exit, right?"
950
+ # exception handling
951
+ end
952
+
953
+ # good
954
+ begin
955
+ # a blind rescue rescues from StandardError, not Exception.
956
+ rescue => error
957
+ # exception handling
958
+ end
959
+ ~~~
960
+
961
+ * Prefer exceptions from the standard library over introducing new exception
962
+ classes.
963
+
964
+ * Use meaningful names for exception variables.
965
+
966
+ ~~~ ruby
967
+ # bad
968
+ begin
969
+ # an exception occurs here
970
+ rescue => e
971
+ # exception handling
972
+ end
973
+
974
+ # good
975
+ begin
976
+ # an exception occurs here
977
+ rescue => error
978
+ # exception handling
979
+ end
980
+ ~~~
981
+
982
+ ## Collections
983
+
984
+ * Use literal array and hash creation notation unless you need to pass
985
+ parameters to their constructors.
986
+
987
+ ~~~ ruby
988
+ # bad
989
+ arr = Array.new
990
+ hash = Hash.new
991
+
992
+ # good
993
+ arr = []
994
+ hash = {}
995
+ ~~~
996
+
997
+ * Prefer the literal array syntax over `%w` or `%i`.
998
+
999
+ ~~~ ruby
1000
+ # bad
1001
+ STATES = %w(draft open closed)
1002
+
1003
+ # good
1004
+ STATES = ["draft", "open", "closed"]
1005
+ ~~~
1006
+
1007
+ * Append a trailing comma in multi-line collection literals.
1008
+
1009
+ ~~~ ruby
1010
+ # bad
1011
+ {
1012
+ foo: :bar,
1013
+ baz: :toto
1014
+ }
1015
+
1016
+ # good
1017
+ {
1018
+ foo: :bar,
1019
+ baz: :toto,
1020
+ }
1021
+ ~~~
1022
+
1023
+ * When accessing the first or last element from an array, prefer `first` or
1024
+ `last` over `[0]` or `[-1]`.
1025
+
1026
+ * Avoid mutable objects as hash keys.
1027
+
1028
+ * Use shorthand hash literal syntax when all keys are symbols.
1029
+
1030
+ ~~~ ruby
1031
+ # bad
1032
+ { :a => 1, :b => 2 }
1033
+
1034
+ # good
1035
+ { a: 1, b: 2 }
1036
+ ~~~
1037
+
1038
+ * Prefer hash rockets syntax over shorthand syntax when not all keys are
1039
+ symbols.
1040
+
1041
+ ~~~ ruby
1042
+ # bad
1043
+ { a: 1, "b" => 2 }
1044
+
1045
+ # good
1046
+ { :a => 1, "b" => 2 }
1047
+ ~~~
1048
+
1049
+ * Prefer `Hash#key?` over `Hash#has_key?`.
1050
+
1051
+ * Prefer `Hash#value?` over `Hash#has_value?`.
1052
+
1053
+ * Use `Hash#fetch` when dealing with hash keys that should be present.
1054
+
1055
+ ~~~ ruby
1056
+ heroes = { batman: "Bruce Wayne", superman: "Clark Kent" }
1057
+ # bad - if we make a mistake we might not spot it right away
1058
+ heroes[:batman] # => "Bruce Wayne"
1059
+ heroes[:supermann] # => nil
1060
+
1061
+ # good - fetch raises a KeyError making the problem obvious
1062
+ heroes.fetch(:supermann)
1063
+ ~~~
1064
+
1065
+ * Introduce default values for hash keys via `Hash#fetch` as opposed to using
1066
+ custom logic.
1067
+
1068
+ ~~~ ruby
1069
+ batman = { name: "Bruce Wayne", is_evil: false }
1070
+
1071
+ # bad - if we just use || operator with falsy value we won't get the expected result
1072
+ batman[:is_evil] || true # => true
1073
+
1074
+ # good - fetch work correctly with falsy values
1075
+ batman.fetch(:is_evil, true) # => false
1076
+ ~~~
1077
+
1078
+ * Place `]` and `}` on the line after the last element when opening
1079
+ brace is on a separate line from the first element.
1080
+
1081
+ ~~~ ruby
1082
+ # bad
1083
+ [
1084
+ 1,
1085
+ 2]
1086
+
1087
+ {
1088
+ a: 1,
1089
+ b: 2}
1090
+
1091
+ # good
1092
+ [
1093
+ 1,
1094
+ 2,
1095
+ ]
1096
+
1097
+ {
1098
+ a: 1,
1099
+ b: 2,
1100
+ }
1101
+ ~~~
1102
+
1103
+ ## Strings
1104
+
1105
+ * Prefer string interpolation and string formatting instead of string
1106
+ concatenation:
1107
+
1108
+ ~~~ ruby
1109
+ # bad
1110
+ email_with_name = user.name + " <" + user.email + ">"
1111
+
1112
+ # good
1113
+ email_with_name = "#{user.name} <#{user.email}>"
1114
+
1115
+ # good
1116
+ email_with_name = format("%s <%s>", user.name, user.email)
1117
+ ~~~
1118
+
1119
+ * Avoid padded-spacing inside braces in interpolated expressions.
1120
+
1121
+ ~~~ ruby
1122
+ # bad
1123
+ "From: #{ user.first_name }, #{ user.last_name }"
1124
+
1125
+ # good
1126
+ "From: #{user.first_name}, #{user.last_name}"
1127
+ ~~~
1128
+
1129
+ * Use double-quoted strings.
1130
+
1131
+ ~~~ ruby
1132
+ # bad
1133
+ 'Just some text'
1134
+ 'No special chars or interpolation'
1135
+
1136
+ # good
1137
+ "Just some text"
1138
+ "No special chars or interpolation"
1139
+ "Every string in #{project} uses double_quotes"
1140
+ ~~~
1141
+
1142
+ * Avoid the character literal syntax `?x`.
1143
+
1144
+ * Use `{}` around instance and global variables being interpolated into a
1145
+ string.
1146
+
1147
+ ~~~ ruby
1148
+ class Person
1149
+ attr_reader :first_name, :last_name
1150
+
1151
+ def initialize(first_name, last_name)
1152
+ @first_name = first_name
1153
+ @last_name = last_name
1154
+ end
1155
+
1156
+ # bad - valid, but awkward
1157
+ def to_s
1158
+ "#@first_name #@last_name"
1159
+ end
1160
+
1161
+ # good
1162
+ def to_s
1163
+ "#{@first_name} #{@last_name}"
1164
+ end
1165
+ end
1166
+
1167
+ $global = 0
1168
+ # bad
1169
+ puts "$global = #$global"
1170
+
1171
+ # fine, but don't use globals
1172
+ puts "$global = #{$global}"
1173
+ ~~~
1174
+
1175
+ * Avoid `Object#to_s` on interpolated objects.
1176
+
1177
+ ~~~ ruby
1178
+ # bad
1179
+ message = "This is the #{result.to_s}."
1180
+
1181
+ # good - `result.to_s` is called implicitly.
1182
+ message = "This is the #{result}."
1183
+ ~~~
1184
+
1185
+ * Avoid `String#gsub` in scenarios in which you can use a faster more
1186
+ specialized alternative.
1187
+
1188
+ ~~~ ruby
1189
+ url = "http://example.com"
1190
+ str = "lisp-case-rules"
1191
+
1192
+ # bad
1193
+ url.gsub("http://", "https://")
1194
+ str.gsub("-", "_")
1195
+ str.gsub(/[aeiou]/, "")
1196
+
1197
+ # good
1198
+ url.sub("http://", "https://")
1199
+ str.tr("-", "_")
1200
+ str.delete("aeiou")
1201
+ ~~~
1202
+
1203
+ * When using heredocs for multi-line strings keep in mind the fact that they
1204
+ preserve leading whitespace. It's a good practice to employ some margin based
1205
+ on which to trim the excessive whitespace.
1206
+
1207
+ ~~~ ruby
1208
+ code = <<-END.gsub(/^\s+\|/, "")
1209
+ |def test
1210
+ | some_method
1211
+ | other_method
1212
+ |end
1213
+ END
1214
+ # => "def test\n some_method\n other_method\nend\n"
1215
+
1216
+ # In Rails you can use `#strip_heredoc` to achieve the same result
1217
+ code = <<-END.strip_heredoc
1218
+ def test
1219
+ some_method
1220
+ other_method
1221
+ end
1222
+ END
1223
+ # => "def test\n some_method\n other_method\nend\n"
1224
+ ~~~
1225
+
1226
+ * In Ruby 2.3, prefer ["squiggly
1227
+ heredoc"](https://github.com/ruby/ruby/pull/878) syntax, which has the same
1228
+ semantics as `strip_heredoc` from Rails:
1229
+
1230
+ ~~~ruby
1231
+ code = <<~END
1232
+ def test
1233
+ some_method
1234
+ other_method
1235
+ end
1236
+ END
1237
+ # => "def test\n some_method\n other_method\nend\n"
1238
+ ~~~
1239
+
1240
+ * Indent heredoc contents and closing according to its opening.
1241
+
1242
+ ~~~ruby
1243
+ # bad
1244
+ class Foo
1245
+ def bar
1246
+ <<~SQL
1247
+ 'Hi'
1248
+ SQL
1249
+ end
1250
+ end
1251
+
1252
+ # good
1253
+ class Foo
1254
+ def bar
1255
+ <<~SQL
1256
+ 'Hi'
1257
+ SQL
1258
+ end
1259
+ end
1260
+
1261
+ # bad
1262
+
1263
+ # heredoc contents is before closing heredoc.
1264
+ foo arg,
1265
+ <<~EOS
1266
+ Hi
1267
+ EOS
1268
+
1269
+ # good
1270
+ foo arg,
1271
+ <<~EOS
1272
+ Hi
1273
+ EOS
1274
+
1275
+ # good
1276
+ foo arg,
1277
+ <<~EOS
1278
+ Hi
1279
+ EOS
1280
+ ~~~
1281
+
1282
+ ## Regular Expressions
1283
+
1284
+ * Prefer plain text search over regular expressions in strings.
1285
+
1286
+ ~~~ ruby
1287
+ string["text"]
1288
+ ~~~
1289
+
1290
+ * Use non-capturing groups when you don't use the captured result.
1291
+
1292
+ ~~~ ruby
1293
+ # bad
1294
+ /(first|second)/
1295
+
1296
+ # good
1297
+ /(?:first|second)/
1298
+ ~~~
1299
+
1300
+ * Prefer `Regexp#match` over Perl-legacy variables to capture group matches.
1301
+
1302
+ ~~~ ruby
1303
+ # bad
1304
+ /(regexp)/ =~ string
1305
+ process $1
1306
+
1307
+ # good
1308
+ /(regexp)/.match(string)[1]
1309
+ ~~~
1310
+
1311
+ * Prefer named groups over numbered groups.
1312
+
1313
+ ~~~ ruby
1314
+ # bad
1315
+ /(regexp)/ =~ string
1316
+ ...
1317
+ process Regexp.last_match(1)
1318
+
1319
+ # good
1320
+ /(?<meaningful_var>regexp)/ =~ string
1321
+ ...
1322
+ process meaningful_var
1323
+ ~~~
1324
+
1325
+ * Prefer `\A` and `\z` over `^` and `$` when matching strings from start to end.
1326
+
1327
+ ~~~ ruby
1328
+ string = "some injection\nusername"
1329
+ string[/^username$/] # `^` and `$` matches start and end of lines.
1330
+ string[/\Ausername\z/] # `\A` and `\z` matches start and end of strings.
1331
+ ~~~
1332
+
1333
+ ## Percent Literals
1334
+
1335
+ * Use `%()` for single-line strings which require both interpolation and
1336
+ embedded double-quotes. For multi-line strings, prefer heredocs.
1337
+
1338
+ * Avoid `%q` unless you have a string with both `'` and `"` in it. Regular
1339
+ string literals are more readable and should be preferred unless a lot of
1340
+ characters would have to be escaped in them.
1341
+
1342
+ * Use `%r` only for regular expressions matching at least one `/` character.
1343
+
1344
+ ~~~ ruby
1345
+ # bad
1346
+ %r{\s+}
1347
+
1348
+ # good
1349
+ %r{^/(.*)$}
1350
+ %r{^/blog/2011/(.*)$}
1351
+ ~~~
1352
+
1353
+ * Avoid the use of `%s`. Use `:"some string"` to create a symbol with spaces in
1354
+ it.
1355
+
1356
+ * Prefer `()` as delimiters for all `%` literals, except, as often occurs in
1357
+ regular expressions, when parentheses appear inside the literal. Use the first
1358
+ of `()`, `{}`, `[]`, `<>` which does not appear inside the literal.
1359
+
1360
+ ## Testing
1361
+
1362
+ * Treat test code like any other code you write. This means: keep readability,
1363
+ maintainability, complexity, etc. in mind.
1364
+
1365
+ * Prefer Minitest as the test framework.
1366
+
1367
+ * Limit each test case to cover a single aspect of your code.
1368
+
1369
+ * Organize the setup, action, and assertion sections of the test case into
1370
+ paragraphs separated by empty lines.
1371
+
1372
+ ~~~ ruby
1373
+ test "sending a password reset email clears the password hash and set a reset token" do
1374
+ user = User.create!(email: "bob@example.com")
1375
+ user.mark_as_verified
1376
+
1377
+ user.send_password_reset_email
1378
+
1379
+ assert_nil user.password_hash
1380
+ refute_nil user.reset_token
1381
+ end
1382
+ ~~~
1383
+
1384
+ * Split complex test cases into multiple simpler tests that test functionality
1385
+ in isolation.
1386
+
1387
+ * Prefer using `test "foo"`-style syntax to define test cases over `def
1388
+ test_foo`.
1389
+
1390
+ * Prefer using assertion methods that will yield a more descriptive error
1391
+ message.
1392
+
1393
+ ~~~ ruby
1394
+ # bad
1395
+ assert user.valid?
1396
+ assert user.name == "tobi"
1397
+
1398
+
1399
+ # good
1400
+ assert_predicate user, :valid?
1401
+ assert_equal "tobi", user.name
1402
+ ~~~
1403
+
1404
+ * Avoid using `assert_nothing_raised`. Use a positive assertion instead.
1405
+
1406
+ * Prefer using assertions over expectations. Expectations lead to more brittle
1407
+ tests, especially in combination with singleton objects.
1408
+
1409
+ ~~~ ruby
1410
+ # bad
1411
+ StatsD.expects(:increment).with("metric")
1412
+ do_something
1413
+
1414
+ # good
1415
+ assert_statsd_increment("metric") do
1416
+ do_something
1417
+ end
1418
+ ~~~