voxable-style-guide 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitattributes +1 -0
- data/.gitignore +12 -0
- data/.idea/encodings.xml +6 -0
- data/.idea/misc.xml +4 -0
- data/.idea/modules.xml +8 -0
- data/.idea/ruby-style-guide.iml +16 -0
- data/.idea/workspace.xml +33 -0
- data/.rspec +2 -0
- data/.rubocop.yml +34 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +4235 -0
- data/Rakefile +1 -0
- data/lib/voxable/ruby_style_guide.rb +5 -0
- data/lib/voxable/ruby_style_guide/version.rb +5 -0
- data/ruby-style-guide.gemspec +23 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5beadb055e7e81a46a9456e12abaa8b61d134c61
|
4
|
+
data.tar.gz: 3fe9524f8a573c2bae472b895e0f66a783c7f941
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1d037aedd8cd02fc3f89c3a1c4b35ad1b6815955143f113c7da74c5ee410afaf620327ea78bcf89fffbd21630ff5369d018d34bf3a879de79599ea5f72e6a3f4
|
7
|
+
data.tar.gz: 0f438884dad350aa66ec988130ccedb664c99f45283aa1d212ff0548acc759259015be1e71d51aa1dbd042ae119048d516e17fc30a4f1ccc04c892d3fc93d0a3
|
data/.gitattributes
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.md whitespace=trailing-space,tab-in-indent
|
data/.gitignore
ADDED
data/.idea/encodings.xml
ADDED
data/.idea/misc.xml
ADDED
data/.idea/modules.xml
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<project version="4">
|
3
|
+
<component name="ProjectModuleManager">
|
4
|
+
<modules>
|
5
|
+
<module fileurl="file://$PROJECT_DIR$/.idea/ruby-style-guide.iml" filepath="$PROJECT_DIR$/.idea/ruby-style-guide.iml" />
|
6
|
+
</modules>
|
7
|
+
</component>
|
8
|
+
</project>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<module type="RUBY_MODULE" version="4">
|
3
|
+
<component name="CompassSettings">
|
4
|
+
<option name="compassExecutableFilePath" value="$USER_HOME$/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/compass-1.0.3/bin/compass" />
|
5
|
+
</component>
|
6
|
+
<component name="ModuleRunConfigurationManager">
|
7
|
+
<shared />
|
8
|
+
<local />
|
9
|
+
</component>
|
10
|
+
<component name="NewModuleRootManager">
|
11
|
+
<content url="file://$MODULE_DIR$" />
|
12
|
+
<orderEntry type="inheritedJdk" />
|
13
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
14
|
+
<orderEntry type="library" scope="PROVIDED" name="rake (v10.5.0, rbenv: 2.3.1) [gem]" level="application" />
|
15
|
+
</component>
|
16
|
+
</module>
|
data/.idea/workspace.xml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<project version="4">
|
3
|
+
<component name="ChangeListManager">
|
4
|
+
<option name="TRACKING_ENABLED" value="true" />
|
5
|
+
<option name="SHOW_DIALOG" value="false" />
|
6
|
+
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
7
|
+
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
8
|
+
<option name="LAST_RESOLUTION" value="IGNORE" />
|
9
|
+
</component>
|
10
|
+
<component name="PropertiesComponent">
|
11
|
+
<property name="settings.editor.selected.configurable" value="database.main" />
|
12
|
+
<property name="settings.editor.splitter.proportion" value="0.2" />
|
13
|
+
</component>
|
14
|
+
<component name="ShelveChangesManager" show_recycled="false">
|
15
|
+
<option name="remove_strategy" value="false" />
|
16
|
+
</component>
|
17
|
+
<component name="TaskManager">
|
18
|
+
<task active="true" id="Default" summary="Default task">
|
19
|
+
<created>1497071587954</created>
|
20
|
+
<option name="number" value="Default" />
|
21
|
+
<option name="presentableId" value="Default" />
|
22
|
+
<updated>1497071587954</updated>
|
23
|
+
</task>
|
24
|
+
<servers />
|
25
|
+
</component>
|
26
|
+
<component name="VcsContentAnnotationSettings">
|
27
|
+
<option name="myLimit" value="2678400000" />
|
28
|
+
</component>
|
29
|
+
<component name="XDebuggerManager">
|
30
|
+
<breakpoint-manager />
|
31
|
+
<watches-manager />
|
32
|
+
</component>
|
33
|
+
</project>
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
AllCops:
|
2
|
+
EnabledByDefault: true
|
3
|
+
DisplayStyleGuide: true
|
4
|
+
StyleGuideBaseURL: https://github.com/voxable-labs/voxable-style-guide
|
5
|
+
|
6
|
+
# Don't require copyright notices
|
7
|
+
Style/Copyright:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
# --||----------------------
|
11
|
+
# || RSpec
|
12
|
+
# ==||======================
|
13
|
+
|
14
|
+
# Use braces for block delimiters in RSpec.
|
15
|
+
Style/BlockDelimiters:
|
16
|
+
EnforcedStyle: semantic
|
17
|
+
FunctionalMethods:
|
18
|
+
- before
|
19
|
+
- let
|
20
|
+
- let!
|
21
|
+
- subject
|
22
|
+
- watch
|
23
|
+
- expect
|
24
|
+
|
25
|
+
# Ignore absence of method call parentheses in RSpec and gemspecs.
|
26
|
+
Style/MethodCallWithArgsParentheses:
|
27
|
+
Exclude:
|
28
|
+
- spec/**/*.rb
|
29
|
+
- ./*.gemspec
|
30
|
+
|
31
|
+
# Ignore block length in RSPec.
|
32
|
+
Metrics/BlockLength:
|
33
|
+
Exclude:
|
34
|
+
- spec/**/*.rb
|
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at github@matthewbuck.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
* [Fork](https://help.github.com/articles/fork-a-repo) the project on GitHub.
|
2
|
+
* Make your feature addition or bug fix in a feature branch. (Include a description of your changes)
|
3
|
+
* Push your feature branch to GitHub.
|
4
|
+
* Send a [Pull Request](https://help.github.com/articles/using-pull-requests).
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Matt Buck
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,4235 @@
|
|
1
|
+
# Voxable's Ruby Style Guide
|
2
|
+
|
3
|
+
This Ruby style guide is the official reference for all of [Voxable](https://voxable.io)'s Ruby projects. It recommends best practices so that real-world Ruby programmers can write code that can be maintained by other real-world Ruby programmers. A style guide that reflects real-world usage gets used, while a style guide that holds to an ideal that has been rejected by the people it is supposed to help risks not getting used at all—no matter how good it is.
|
4
|
+
|
5
|
+
There are some areas in which there is no clear consensus in the Ruby community regarding a particular style (like string literal quoting, spacing inside hash literals, dot position in multi-line method chaining, etc.). In such scenarios all popular styles are acknowledged and it's up to you to pick one and apply it consistently.
|
6
|
+
|
7
|
+
This style guide evolves over time as additional conventions are identified and past conventions are rendered obsolete by changes in Ruby itself.
|
8
|
+
|
9
|
+
## RuboCop Integration
|
10
|
+
|
11
|
+
This repo's `.rubocop.yml` file encodes this style guide as a [RuboCop](https://github.com/bbatsov/rubocop) configuration. To include it in your project, add the following to the top of your project's `.rubocop.yml`:
|
12
|
+
|
13
|
+
```yaml
|
14
|
+
inherit_from:
|
15
|
+
- https://raw.githubusercontent.com/voxable-labs/ruby-style-guide/master/.rubocop.yml
|
16
|
+
```
|
17
|
+
|
18
|
+
You'll also want to add its cache file to your `.gitignore`:
|
19
|
+
|
20
|
+
```
|
21
|
+
# RuboCop config cache file
|
22
|
+
.rubocop-https---raw-githubusercontent-com-voxable-labs-ruby-style-guide-master--rubocop-yml
|
23
|
+
```
|
24
|
+
|
25
|
+
If you need to bust this cache file to pick up the latest changes to the guide (which should happen automatically every 24 hours), you can simply delete the cache file from your project.
|
26
|
+
|
27
|
+
## Credits
|
28
|
+
|
29
|
+
We didn't come up with all the rules out of nowhere. In fact, this repo started life as a fork of [bbatsov](https://github.com/bbatsov)'s excellent [`ruby-style-guide`](https://github.com/bbatsov/ruby-style-guide), with a few changes
|
30
|
+
that happen to suit our tastes.
|
31
|
+
|
32
|
+
## Table of Contents
|
33
|
+
|
34
|
+
* [Source Code Layout](#source-code-layout)
|
35
|
+
* [Syntax](#syntax)
|
36
|
+
* [Naming](#naming)
|
37
|
+
* [Comments](#comments)
|
38
|
+
* [Comment Annotations](#comment-annotations)
|
39
|
+
* [Magic Comments](#magic-comments)
|
40
|
+
* [Classes & Modules](#classes--modules)
|
41
|
+
* [Exceptions](#exceptions)
|
42
|
+
* [Collections](#collections)
|
43
|
+
* [Numbers](#numbers)
|
44
|
+
* [Strings](#strings)
|
45
|
+
* [Date & Time](#date--time)
|
46
|
+
* [Regular Expressions](#regular-expressions)
|
47
|
+
* [Percent Literals](#percent-literals)
|
48
|
+
* [Metaprogramming](#metaprogramming)
|
49
|
+
* [Misc](#misc)
|
50
|
+
* [Tools](#tools)
|
51
|
+
|
52
|
+
## Source Code Layout
|
53
|
+
|
54
|
+
> Nearly everybody is convinced that every style but their own is
|
55
|
+
> ugly and unreadable. Leave out the "but their own" and they're
|
56
|
+
> probably right... <br>
|
57
|
+
> -- Jerry Coffin (on indentation)
|
58
|
+
|
59
|
+
* <a name="utf-8"></a>
|
60
|
+
Use `UTF-8` as the source file encoding.
|
61
|
+
<sup>[[link](#utf-8)]</sup>
|
62
|
+
|
63
|
+
* <a name="spaces-indentation"></a>
|
64
|
+
Use two **spaces** per indentation level (aka soft tabs). No hard tabs.
|
65
|
+
<sup>[[link](#spaces-indentation)]</sup>
|
66
|
+
|
67
|
+
```Ruby
|
68
|
+
# bad - four spaces
|
69
|
+
def some_method
|
70
|
+
do_something
|
71
|
+
end
|
72
|
+
|
73
|
+
# good
|
74
|
+
def some_method
|
75
|
+
do_something
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
* <a name="crlf"></a>
|
80
|
+
Use Unix-style line endings. (\*BSD/Solaris/Linux/macOS users are covered by
|
81
|
+
default, Windows users have to be extra careful.)
|
82
|
+
<sup>[[link](#crlf)]</sup>
|
83
|
+
|
84
|
+
* If you're using Git you might want to add the following
|
85
|
+
configuration setting to protect your project from Windows line
|
86
|
+
endings creeping in:
|
87
|
+
|
88
|
+
```bash
|
89
|
+
$ git config --global core.autocrlf true
|
90
|
+
```
|
91
|
+
|
92
|
+
* <a name="no-semicolon"></a>
|
93
|
+
Don't use `;` to separate statements and expressions. As a corollary—use
|
94
|
+
one expression per line.
|
95
|
+
<sup>[[link](#no-semicolon)]</sup>
|
96
|
+
|
97
|
+
```Ruby
|
98
|
+
# bad
|
99
|
+
puts 'foobar'; # superfluous semicolon
|
100
|
+
|
101
|
+
puts 'foo'; puts 'bar' # two expressions on the same line
|
102
|
+
|
103
|
+
# good
|
104
|
+
puts 'foobar'
|
105
|
+
|
106
|
+
puts 'foo'
|
107
|
+
puts 'bar'
|
108
|
+
|
109
|
+
puts 'foo', 'bar' # this applies to puts in particular
|
110
|
+
```
|
111
|
+
|
112
|
+
* <a name="single-line-classes"></a>
|
113
|
+
Prefer a single-line format for class definitions with no body.
|
114
|
+
<sup>[[link](#single-line-classes)]</sup>
|
115
|
+
|
116
|
+
```Ruby
|
117
|
+
# bad
|
118
|
+
class FooError < StandardError
|
119
|
+
end
|
120
|
+
|
121
|
+
# okish
|
122
|
+
class FooError < StandardError; end
|
123
|
+
|
124
|
+
# good
|
125
|
+
FooError = Class.new(StandardError)
|
126
|
+
```
|
127
|
+
|
128
|
+
* <a name="no-single-line-methods"></a>
|
129
|
+
Avoid single-line methods. Although they are somewhat popular in the wild,
|
130
|
+
there are a few peculiarities about their definition syntax that make their
|
131
|
+
use undesirable. At any rate—there should be no more than one expression
|
132
|
+
in a single-line method.
|
133
|
+
<sup>[[link](#no-single-line-methods)]</sup>
|
134
|
+
|
135
|
+
```Ruby
|
136
|
+
# bad
|
137
|
+
def too_much; something; something_else; end
|
138
|
+
|
139
|
+
# okish - notice that the first ; is required
|
140
|
+
def no_braces_method; body end
|
141
|
+
|
142
|
+
# okish - notice that the second ; is optional
|
143
|
+
def no_braces_method; body; end
|
144
|
+
|
145
|
+
# okish - valid syntax, but no ; makes it kind of hard to read
|
146
|
+
def some_method() body end
|
147
|
+
|
148
|
+
# good
|
149
|
+
def some_method
|
150
|
+
body
|
151
|
+
end
|
152
|
+
```
|
153
|
+
|
154
|
+
One exception to the rule are empty-body methods.
|
155
|
+
|
156
|
+
```Ruby
|
157
|
+
# good
|
158
|
+
def no_op; end
|
159
|
+
```
|
160
|
+
|
161
|
+
* <a name="spaces-operators"></a>
|
162
|
+
Use spaces around operators, after commas, colons and semicolons.
|
163
|
+
Whitespace might be (mostly) irrelevant to the Ruby interpreter,
|
164
|
+
but its proper use is the key to writing easily readable code.
|
165
|
+
<sup>[[link](#spaces-operators)]</sup>
|
166
|
+
|
167
|
+
```Ruby
|
168
|
+
sum = 1 + 2
|
169
|
+
a, b = 1, 2
|
170
|
+
class FooError < StandardError; end
|
171
|
+
```
|
172
|
+
|
173
|
+
The only exception, regarding operators, is the exponent operator:
|
174
|
+
|
175
|
+
```Ruby
|
176
|
+
# bad
|
177
|
+
e = M * c ** 2
|
178
|
+
|
179
|
+
# good
|
180
|
+
e = M * c**2
|
181
|
+
```
|
182
|
+
|
183
|
+
* <a name="spaces-braces"></a>
|
184
|
+
No spaces after `(`, `[` or before `]`, `)`.
|
185
|
+
Use spaces around `{` and before `}`.
|
186
|
+
<sup>[[link](#spaces-braces)]</sup>
|
187
|
+
|
188
|
+
```Ruby
|
189
|
+
# bad
|
190
|
+
some( arg ).other
|
191
|
+
[ 1, 2, 3 ].each{|e| puts e}
|
192
|
+
|
193
|
+
# good
|
194
|
+
some(arg).other
|
195
|
+
[1, 2, 3].each { |e| puts e }
|
196
|
+
```
|
197
|
+
|
198
|
+
`{` and `}` deserve a bit of clarification, since they are used
|
199
|
+
for block and hash literals, as well as string interpolation.
|
200
|
+
|
201
|
+
For hash literals two styles are considered acceptable.
|
202
|
+
The first variant is slightly more readable (and arguably more
|
203
|
+
popular in the Ruby community in general). The second variant has
|
204
|
+
the advantage of adding visual difference between block and hash
|
205
|
+
literals. Whichever one you pick—apply it consistently.
|
206
|
+
|
207
|
+
```Ruby
|
208
|
+
# good - space after { and before }
|
209
|
+
{ one: 1, two: 2 }
|
210
|
+
|
211
|
+
# good - no space after { and before }
|
212
|
+
{one: 1, two: 2}
|
213
|
+
```
|
214
|
+
|
215
|
+
With interpolated expressions, there should be no padded-spacing inside the braces.
|
216
|
+
|
217
|
+
```Ruby
|
218
|
+
# bad
|
219
|
+
"From: #{ user.first_name }, #{ user.last_name }"
|
220
|
+
|
221
|
+
# good
|
222
|
+
"From: #{user.first_name}, #{user.last_name}"
|
223
|
+
```
|
224
|
+
|
225
|
+
* <a name="no-space-bang"></a>
|
226
|
+
No space after `!`.
|
227
|
+
<sup>[[link](#no-space-bang)]</sup>
|
228
|
+
|
229
|
+
```Ruby
|
230
|
+
# bad
|
231
|
+
! something
|
232
|
+
|
233
|
+
# good
|
234
|
+
!something
|
235
|
+
```
|
236
|
+
|
237
|
+
* <a name="no-space-inside-range-literals"></a>
|
238
|
+
No space inside range literals.
|
239
|
+
<sup>[[link](#no-space-inside-range-literals)]</sup>
|
240
|
+
|
241
|
+
```Ruby
|
242
|
+
# bad
|
243
|
+
1 .. 3
|
244
|
+
'a' ... 'z'
|
245
|
+
|
246
|
+
# good
|
247
|
+
1..3
|
248
|
+
'a'...'z'
|
249
|
+
```
|
250
|
+
|
251
|
+
* <a name="indent-when-to-case"></a>
|
252
|
+
Indent `when` as deep as `case`. This is the style established in both
|
253
|
+
"The Ruby Programming Language" and "Programming Ruby".
|
254
|
+
<sup>[[link](#indent-when-to-case)]</sup>
|
255
|
+
|
256
|
+
```Ruby
|
257
|
+
# bad
|
258
|
+
case
|
259
|
+
when song.name == 'Misty'
|
260
|
+
puts 'Not again!'
|
261
|
+
when song.duration > 120
|
262
|
+
puts 'Too long!'
|
263
|
+
when Time.now.hour > 21
|
264
|
+
puts "It's too late"
|
265
|
+
else
|
266
|
+
song.play
|
267
|
+
end
|
268
|
+
|
269
|
+
# good
|
270
|
+
case
|
271
|
+
when song.name == 'Misty'
|
272
|
+
puts 'Not again!'
|
273
|
+
when song.duration > 120
|
274
|
+
puts 'Too long!'
|
275
|
+
when Time.now.hour > 21
|
276
|
+
puts "It's too late"
|
277
|
+
else
|
278
|
+
song.play
|
279
|
+
end
|
280
|
+
```
|
281
|
+
|
282
|
+
* <a name="indent-conditional-assignment"></a>
|
283
|
+
When assigning the result of a conditional expression to a variable,
|
284
|
+
preserve the usual alignment of its branches.
|
285
|
+
<sup>[[link](#indent-conditional-assignment)]</sup>
|
286
|
+
|
287
|
+
```Ruby
|
288
|
+
# bad - pretty convoluted
|
289
|
+
kind = case year
|
290
|
+
when 1850..1889 then 'Blues'
|
291
|
+
when 1890..1909 then 'Ragtime'
|
292
|
+
when 1910..1929 then 'New Orleans Jazz'
|
293
|
+
when 1930..1939 then 'Swing'
|
294
|
+
when 1940..1950 then 'Bebop'
|
295
|
+
else 'Jazz'
|
296
|
+
end
|
297
|
+
|
298
|
+
result = if some_cond
|
299
|
+
calc_something
|
300
|
+
else
|
301
|
+
calc_something_else
|
302
|
+
end
|
303
|
+
|
304
|
+
# good - it's apparent what's going on
|
305
|
+
kind = case year
|
306
|
+
when 1850..1889 then 'Blues'
|
307
|
+
when 1890..1909 then 'Ragtime'
|
308
|
+
when 1910..1929 then 'New Orleans Jazz'
|
309
|
+
when 1930..1939 then 'Swing'
|
310
|
+
when 1940..1950 then 'Bebop'
|
311
|
+
else 'Jazz'
|
312
|
+
end
|
313
|
+
|
314
|
+
result = if some_cond
|
315
|
+
calc_something
|
316
|
+
else
|
317
|
+
calc_something_else
|
318
|
+
end
|
319
|
+
|
320
|
+
# good (and a bit more width efficient)
|
321
|
+
kind =
|
322
|
+
case year
|
323
|
+
when 1850..1889 then 'Blues'
|
324
|
+
when 1890..1909 then 'Ragtime'
|
325
|
+
when 1910..1929 then 'New Orleans Jazz'
|
326
|
+
when 1930..1939 then 'Swing'
|
327
|
+
when 1940..1950 then 'Bebop'
|
328
|
+
else 'Jazz'
|
329
|
+
end
|
330
|
+
|
331
|
+
result =
|
332
|
+
if some_cond
|
333
|
+
calc_something
|
334
|
+
else
|
335
|
+
calc_something_else
|
336
|
+
end
|
337
|
+
```
|
338
|
+
|
339
|
+
* <a name="empty-lines-between-methods"></a>
|
340
|
+
Use empty lines between method definitions and also to break up methods
|
341
|
+
into logical paragraphs internally.
|
342
|
+
<sup>[[link](#empty-lines-between-methods)]</sup>
|
343
|
+
|
344
|
+
```Ruby
|
345
|
+
def some_method
|
346
|
+
data = initialize(options)
|
347
|
+
|
348
|
+
data.manipulate!
|
349
|
+
|
350
|
+
data.result
|
351
|
+
end
|
352
|
+
|
353
|
+
def some_method
|
354
|
+
result
|
355
|
+
end
|
356
|
+
```
|
357
|
+
|
358
|
+
* <a name="two-or-more-empty-lines"></a>
|
359
|
+
Don't use several empty lines in a row.
|
360
|
+
<sup>[[link](#two-or-more-empty-lines)]</sup>
|
361
|
+
|
362
|
+
```Ruby
|
363
|
+
# bad - It has two empty lines.
|
364
|
+
some_method
|
365
|
+
|
366
|
+
|
367
|
+
some_method
|
368
|
+
|
369
|
+
# good
|
370
|
+
some_method
|
371
|
+
|
372
|
+
some_method
|
373
|
+
```
|
374
|
+
|
375
|
+
* <a name="empty-lines-around-access-modifier"></a>
|
376
|
+
Use empty lines around access modifiers.
|
377
|
+
<sup>[[link](#empty-lines-around-access-modifier)]</sup>
|
378
|
+
|
379
|
+
```Ruby
|
380
|
+
# bad
|
381
|
+
class Foo
|
382
|
+
attr_reader :foo
|
383
|
+
def foo
|
384
|
+
# do something...
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
# good
|
389
|
+
class Foo
|
390
|
+
attr_reader :foo
|
391
|
+
|
392
|
+
def foo
|
393
|
+
# do something...
|
394
|
+
end
|
395
|
+
end
|
396
|
+
```
|
397
|
+
|
398
|
+
* <a name="empty-lines-around-bodies"></a>
|
399
|
+
Don't use empty lines around method, class, module, block bodies.
|
400
|
+
<sup>[[link](#empty-lines-around-bodies)]</sup>
|
401
|
+
|
402
|
+
```Ruby
|
403
|
+
# bad
|
404
|
+
class Foo
|
405
|
+
|
406
|
+
def foo
|
407
|
+
|
408
|
+
begin
|
409
|
+
|
410
|
+
do_something do
|
411
|
+
|
412
|
+
something
|
413
|
+
|
414
|
+
end
|
415
|
+
|
416
|
+
rescue
|
417
|
+
|
418
|
+
something
|
419
|
+
|
420
|
+
end
|
421
|
+
|
422
|
+
end
|
423
|
+
|
424
|
+
end
|
425
|
+
|
426
|
+
# good
|
427
|
+
class Foo
|
428
|
+
def foo
|
429
|
+
begin
|
430
|
+
do_something do
|
431
|
+
something
|
432
|
+
end
|
433
|
+
rescue
|
434
|
+
something
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
```
|
439
|
+
|
440
|
+
* <a name="no-trailing-params-comma"></a>
|
441
|
+
Avoid comma after the last parameter in a method call, especially when the
|
442
|
+
parameters are not on separate lines.
|
443
|
+
<sup>[[link](#no-trailing-params-comma)]</sup>
|
444
|
+
|
445
|
+
```Ruby
|
446
|
+
# bad - easier to move/add/remove parameters, but still not preferred
|
447
|
+
some_method(
|
448
|
+
size,
|
449
|
+
count,
|
450
|
+
color,
|
451
|
+
)
|
452
|
+
|
453
|
+
# bad
|
454
|
+
some_method(size, count, color, )
|
455
|
+
|
456
|
+
# good
|
457
|
+
some_method(size, count, color)
|
458
|
+
```
|
459
|
+
|
460
|
+
* <a name="spaces-around-equals"></a>
|
461
|
+
Use spaces around the `=` operator when assigning default values to method
|
462
|
+
parameters:
|
463
|
+
<sup>[[link](#spaces-around-equals)]</sup>
|
464
|
+
|
465
|
+
```Ruby
|
466
|
+
# bad
|
467
|
+
def some_method(arg1=:default, arg2=nil, arg3=[])
|
468
|
+
# do something...
|
469
|
+
end
|
470
|
+
|
471
|
+
# good
|
472
|
+
def some_method(arg1 = :default, arg2 = nil, arg3 = [])
|
473
|
+
# do something...
|
474
|
+
end
|
475
|
+
```
|
476
|
+
|
477
|
+
While several Ruby books suggest the first style, the second is much more
|
478
|
+
prominent in practice (and arguably a bit more readable).
|
479
|
+
|
480
|
+
* <a name="no-trailing-backslash"></a>
|
481
|
+
Avoid line continuation `\` where not required. In practice, avoid using
|
482
|
+
line continuations for anything but string concatenation.
|
483
|
+
<sup>[[link](#no-trailing-backslash)]</sup>
|
484
|
+
|
485
|
+
```Ruby
|
486
|
+
# bad
|
487
|
+
result = 1 - \
|
488
|
+
2
|
489
|
+
|
490
|
+
# good (but still ugly as hell)
|
491
|
+
result = 1 \
|
492
|
+
- 2
|
493
|
+
|
494
|
+
long_string = 'First part of the long string' \
|
495
|
+
' and second part of the long string'
|
496
|
+
```
|
497
|
+
|
498
|
+
* <a name="consistent-multi-line-chains"></a>
|
499
|
+
Adopt a consistent multi-line method chaining style. There are two popular
|
500
|
+
styles in the Ruby community, both of which are considered
|
501
|
+
good—leading `.` (Option A) and trailing `.` (Option B).
|
502
|
+
<sup>[[link](#consistent-multi-line-chains)]</sup>
|
503
|
+
|
504
|
+
* **(Option A)** When continuing a chained method invocation on
|
505
|
+
another line keep the `.` on the second line.
|
506
|
+
|
507
|
+
```Ruby
|
508
|
+
# bad - need to consult first line to understand second line
|
509
|
+
one.two.three.
|
510
|
+
four
|
511
|
+
|
512
|
+
# good - it's immediately clear what's going on the second line
|
513
|
+
one.two.three
|
514
|
+
.four
|
515
|
+
```
|
516
|
+
|
517
|
+
* **(Option B)** When continuing a chained method invocation on another line,
|
518
|
+
include the `.` on the first line to indicate that the
|
519
|
+
expression continues.
|
520
|
+
|
521
|
+
```Ruby
|
522
|
+
# bad - need to read ahead to the second line to know that the chain continues
|
523
|
+
one.two.three
|
524
|
+
.four
|
525
|
+
|
526
|
+
# good - it's immediately clear that the expression continues beyond the first line
|
527
|
+
one.two.three.
|
528
|
+
four
|
529
|
+
```
|
530
|
+
|
531
|
+
A discussion on the merits of both alternative styles can be found
|
532
|
+
[here](https://github.com/bbatsov/ruby-style-guide/pull/176).
|
533
|
+
|
534
|
+
* <a name="no-double-indent"></a>
|
535
|
+
Align the parameters of a method call if they span more than one
|
536
|
+
line. When aligning parameters is not appropriate due to line-length
|
537
|
+
constraints, single indent for the lines after the first is also
|
538
|
+
acceptable.
|
539
|
+
<sup>[[link](#no-double-indent)]</sup>
|
540
|
+
|
541
|
+
```Ruby
|
542
|
+
# starting point (line is too long)
|
543
|
+
def send_mail(source)
|
544
|
+
Mailer.deliver(to: 'bob@example.com', from: 'us@example.com', subject: 'Important message', body: source.text)
|
545
|
+
end
|
546
|
+
|
547
|
+
# bad (double indent)
|
548
|
+
def send_mail(source)
|
549
|
+
Mailer.deliver(
|
550
|
+
to: 'bob@example.com',
|
551
|
+
from: 'us@example.com',
|
552
|
+
subject: 'Important message',
|
553
|
+
body: source.text)
|
554
|
+
end
|
555
|
+
|
556
|
+
# good
|
557
|
+
def send_mail(source)
|
558
|
+
Mailer.deliver(to: 'bob@example.com',
|
559
|
+
from: 'us@example.com',
|
560
|
+
subject: 'Important message',
|
561
|
+
body: source.text)
|
562
|
+
end
|
563
|
+
|
564
|
+
# good (normal indent)
|
565
|
+
def send_mail(source)
|
566
|
+
Mailer.deliver(
|
567
|
+
to: 'bob@example.com',
|
568
|
+
from: 'us@example.com',
|
569
|
+
subject: 'Important message',
|
570
|
+
body: source.text
|
571
|
+
)
|
572
|
+
end
|
573
|
+
```
|
574
|
+
|
575
|
+
* <a name="align-multiline-arrays"></a>
|
576
|
+
Align the elements of array literals spanning multiple lines.
|
577
|
+
<sup>[[link](#align-multiline-arrays)]</sup>
|
578
|
+
|
579
|
+
```Ruby
|
580
|
+
# bad - single indent
|
581
|
+
menu_item = ['Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam',
|
582
|
+
'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam']
|
583
|
+
|
584
|
+
# good
|
585
|
+
menu_item = [
|
586
|
+
'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam',
|
587
|
+
'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam'
|
588
|
+
]
|
589
|
+
|
590
|
+
# good
|
591
|
+
menu_item =
|
592
|
+
['Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam',
|
593
|
+
'Baked beans', 'Spam', 'Spam', 'Spam', 'Spam', 'Spam']
|
594
|
+
```
|
595
|
+
|
596
|
+
* <a name="underscores-in-numerics"></a>
|
597
|
+
Add underscores to large numeric literals to improve their readability.
|
598
|
+
<sup>[[link](#underscores-in-numerics)]</sup>
|
599
|
+
|
600
|
+
```Ruby
|
601
|
+
# bad - how many 0s are there?
|
602
|
+
num = 1000000
|
603
|
+
|
604
|
+
# good - much easier to parse for the human brain
|
605
|
+
num = 1_000_000
|
606
|
+
```
|
607
|
+
|
608
|
+
* <a name="numeric-literal-prefixes"></a>
|
609
|
+
Prefer smallcase letters for numeric literal prefixes.
|
610
|
+
`0o` for octal, `0x` for hexadecimal and `0b` for binary.
|
611
|
+
Do not use `0d` prefix for decimal literals.
|
612
|
+
<sup>[[link](#numeric-literal-prefixes)]</sup>
|
613
|
+
|
614
|
+
```Ruby
|
615
|
+
# bad
|
616
|
+
num = 01234
|
617
|
+
num = 0O1234
|
618
|
+
num = 0X12AB
|
619
|
+
num = 0B10101
|
620
|
+
num = 0D1234
|
621
|
+
num = 0d1234
|
622
|
+
|
623
|
+
# good - easier to separate digits from the prefix
|
624
|
+
num = 0o1234
|
625
|
+
num = 0x12AB
|
626
|
+
num = 0b10101
|
627
|
+
num = 1234
|
628
|
+
```
|
629
|
+
|
630
|
+
* <a name="rdoc-conventions"></a>
|
631
|
+
Use [Rdoc][rdoc] and its conventions for API documentation. Don't put an
|
632
|
+
empty line between the comment block and the `def`.
|
633
|
+
<sup>[[link](#rdoc-conventions)]</sup>
|
634
|
+
|
635
|
+
* <a name="80-character-limits"></a>
|
636
|
+
Limit lines to 80 characters.
|
637
|
+
<sup>[[link](#80-character-limits)]</sup>
|
638
|
+
|
639
|
+
* <a name="no-trailing-whitespace"></a>
|
640
|
+
Avoid trailing whitespace.
|
641
|
+
<sup>[[link](#no-trailing-whitespace)]</sup>
|
642
|
+
|
643
|
+
* <a name="newline-eof"></a>
|
644
|
+
End each file with a newline.
|
645
|
+
<sup>[[link](#newline-eof)]</sup>
|
646
|
+
|
647
|
+
* <a name="no-block-comments"></a>
|
648
|
+
Don't use block comments. They cannot be preceded by whitespace and are not
|
649
|
+
as easy to spot as regular comments.
|
650
|
+
<sup>[[link](#no-block-comments)]</sup>
|
651
|
+
|
652
|
+
```Ruby
|
653
|
+
# bad
|
654
|
+
=begin
|
655
|
+
comment line
|
656
|
+
another comment line
|
657
|
+
=end
|
658
|
+
|
659
|
+
# good
|
660
|
+
# comment line
|
661
|
+
# another comment line
|
662
|
+
```
|
663
|
+
|
664
|
+
## Syntax
|
665
|
+
|
666
|
+
* <a name="double-colons"></a>
|
667
|
+
Use `::` only to reference constants(this includes classes and
|
668
|
+
modules) and constructors (like `Array()` or `Nokogiri::HTML()`).
|
669
|
+
Do not use `::` for regular method invocation.
|
670
|
+
<sup>[[link](#double-colons)]</sup>
|
671
|
+
|
672
|
+
```Ruby
|
673
|
+
# bad
|
674
|
+
SomeClass::some_method
|
675
|
+
some_object::some_method
|
676
|
+
|
677
|
+
# good
|
678
|
+
SomeClass.some_method
|
679
|
+
some_object.some_method
|
680
|
+
SomeModule::SomeClass::SOME_CONST
|
681
|
+
SomeModule::SomeClass()
|
682
|
+
```
|
683
|
+
|
684
|
+
* <a name="method-parens"></a>
|
685
|
+
Use `def` with parentheses when there are parameters. Omit the
|
686
|
+
parentheses when the method doesn't accept any parameters.
|
687
|
+
<sup>[[link](#method-parens)]</sup>
|
688
|
+
|
689
|
+
```Ruby
|
690
|
+
# bad
|
691
|
+
def some_method()
|
692
|
+
# body omitted
|
693
|
+
end
|
694
|
+
|
695
|
+
# good
|
696
|
+
def some_method
|
697
|
+
# body omitted
|
698
|
+
end
|
699
|
+
|
700
|
+
# bad
|
701
|
+
def some_method_with_parameters param1, param2
|
702
|
+
# body omitted
|
703
|
+
end
|
704
|
+
|
705
|
+
# good
|
706
|
+
def some_method_with_parameters(param1, param2)
|
707
|
+
# body omitted
|
708
|
+
end
|
709
|
+
```
|
710
|
+
|
711
|
+
* <a name="method-invocation-parens"></a>
|
712
|
+
Use parentheses around the arguments of method invocations,
|
713
|
+
especially if the first argument begins with an open parenthesis `(`,
|
714
|
+
as in `f((3 + 2) + 1)`.
|
715
|
+
<sup>[[link](#method-invocation-parens)]</sup>
|
716
|
+
|
717
|
+
```Ruby
|
718
|
+
# bad
|
719
|
+
x = Math.sin y
|
720
|
+
# good
|
721
|
+
x = Math.sin(y)
|
722
|
+
|
723
|
+
# bad
|
724
|
+
array.delete e
|
725
|
+
# good
|
726
|
+
array.delete(e)
|
727
|
+
|
728
|
+
# bad
|
729
|
+
temperance = Person.new 'Temperance', 30
|
730
|
+
# good
|
731
|
+
temperance = Person.new('Temperance', 30)
|
732
|
+
```
|
733
|
+
|
734
|
+
Only omit parentheses for
|
735
|
+
|
736
|
+
* Method calls with no arguments:
|
737
|
+
|
738
|
+
```Ruby
|
739
|
+
# bad
|
740
|
+
Kernel.exit!()
|
741
|
+
2.even?()
|
742
|
+
fork()
|
743
|
+
'test'.upcase()
|
744
|
+
|
745
|
+
# good
|
746
|
+
Kernel.exit!
|
747
|
+
2.even?
|
748
|
+
fork
|
749
|
+
'test'.upcase
|
750
|
+
```
|
751
|
+
|
752
|
+
* Methods that are part of an internal DSL (e.g., Rake, Rails, RSpec):
|
753
|
+
|
754
|
+
```Ruby
|
755
|
+
# bad
|
756
|
+
validates(:name, presence: true)
|
757
|
+
# good
|
758
|
+
validates :name, presence: true
|
759
|
+
```
|
760
|
+
|
761
|
+
* Methods that have "keyword" status in Ruby:
|
762
|
+
|
763
|
+
```Ruby
|
764
|
+
class Person
|
765
|
+
# bad
|
766
|
+
attr_reader(:name, :age)
|
767
|
+
# good
|
768
|
+
attr_reader :name, :age
|
769
|
+
|
770
|
+
# body omitted
|
771
|
+
end
|
772
|
+
|
773
|
+
# bad
|
774
|
+
puts(temperance.age)
|
775
|
+
# good
|
776
|
+
puts temperance.age
|
777
|
+
```
|
778
|
+
|
779
|
+
* <a name="optional-arguments"></a>
|
780
|
+
Define optional arguments at the end of the list of arguments.
|
781
|
+
Ruby has some unexpected results when calling methods that have
|
782
|
+
optional arguments at the front of the list.
|
783
|
+
<sup>[[link](#optional-arguments)]</sup>
|
784
|
+
|
785
|
+
```Ruby
|
786
|
+
# bad
|
787
|
+
def some_method(a = 1, b = 2, c, d)
|
788
|
+
puts "#{a}, #{b}, #{c}, #{d}"
|
789
|
+
end
|
790
|
+
|
791
|
+
some_method('w', 'x') # => '1, 2, w, x'
|
792
|
+
some_method('w', 'x', 'y') # => 'w, 2, x, y'
|
793
|
+
some_method('w', 'x', 'y', 'z') # => 'w, x, y, z'
|
794
|
+
|
795
|
+
# good
|
796
|
+
def some_method(c, d, a = 1, b = 2)
|
797
|
+
puts "#{a}, #{b}, #{c}, #{d}"
|
798
|
+
end
|
799
|
+
|
800
|
+
some_method('w', 'x') # => '1, 2, w, x'
|
801
|
+
some_method('w', 'x', 'y') # => 'y, 2, w, x'
|
802
|
+
some_method('w', 'x', 'y', 'z') # => 'y, z, w, x'
|
803
|
+
```
|
804
|
+
|
805
|
+
* <a name="parallel-assignment"></a>
|
806
|
+
Avoid the use of parallel assignment for defining variables. Parallel
|
807
|
+
assignment is allowed when it is the return of a method call, used with
|
808
|
+
the splat operator, or when used to swap variable assignment. Parallel
|
809
|
+
assignment is less readable than separate assignment.
|
810
|
+
<sup>[[link](#parallel-assignment)]</sup>
|
811
|
+
|
812
|
+
```Ruby
|
813
|
+
# bad
|
814
|
+
a, b, c, d = 'foo', 'bar', 'baz', 'foobar'
|
815
|
+
|
816
|
+
# good
|
817
|
+
a = 'foo'
|
818
|
+
b = 'bar'
|
819
|
+
c = 'baz'
|
820
|
+
d = 'foobar'
|
821
|
+
|
822
|
+
# good - swapping variable assignment
|
823
|
+
# Swapping variable assignment is a special case because it will allow you to
|
824
|
+
# swap the values that are assigned to each variable.
|
825
|
+
a = 'foo'
|
826
|
+
b = 'bar'
|
827
|
+
|
828
|
+
a, b = b, a
|
829
|
+
puts a # => 'bar'
|
830
|
+
puts b # => 'foo'
|
831
|
+
|
832
|
+
# good - method return
|
833
|
+
def multi_return
|
834
|
+
[1, 2]
|
835
|
+
end
|
836
|
+
|
837
|
+
first, second = multi_return
|
838
|
+
|
839
|
+
# good - use with splat
|
840
|
+
first, *list = [1, 2, 3, 4] # first => 1, list => [2, 3, 4]
|
841
|
+
|
842
|
+
hello_array = *'Hello' # => ["Hello"]
|
843
|
+
|
844
|
+
a = *(1..3) # => [1, 2, 3]
|
845
|
+
```
|
846
|
+
|
847
|
+
* <a name="trailing-underscore-variables"></a>
|
848
|
+
Avoid the use of unnecessary trailing underscore variables during
|
849
|
+
parallel assignment. Named underscore variables are to be preferred over
|
850
|
+
underscore variables because of the context that they provide.
|
851
|
+
Trailing underscore variables are necessary when there is a splat variable
|
852
|
+
defined on the left side of the assignment, and the splat variable is
|
853
|
+
not an underscore.
|
854
|
+
<sup>[[link]](#trailing-underscore-variables)</sup>
|
855
|
+
|
856
|
+
```Ruby
|
857
|
+
# bad
|
858
|
+
foo = 'one,two,three,four,five'
|
859
|
+
# Unnecessary assignment that does not provide useful information
|
860
|
+
first, second, _ = foo.split(',')
|
861
|
+
first, _, _ = foo.split(',')
|
862
|
+
first, *_ = foo.split(',')
|
863
|
+
|
864
|
+
|
865
|
+
# good
|
866
|
+
foo = 'one,two,three,four,five'
|
867
|
+
# The underscores are needed to show that you want all elements
|
868
|
+
# except for the last number of underscore elements
|
869
|
+
*beginning, _ = foo.split(',')
|
870
|
+
*beginning, something, _ = foo.split(',')
|
871
|
+
|
872
|
+
a, = foo.split(',')
|
873
|
+
a, b, = foo.split(',')
|
874
|
+
# Unnecessary assignment to an unused variable, but the assignment
|
875
|
+
# provides us with useful information.
|
876
|
+
first, _second = foo.split(',')
|
877
|
+
first, _second, = foo.split(',')
|
878
|
+
first, *_ending = foo.split(',')
|
879
|
+
```
|
880
|
+
|
881
|
+
* <a name="no-for-loops"></a>
|
882
|
+
Do not use `for`, unless you know exactly why. Most of the time iterators
|
883
|
+
should be used instead. `for` is implemented in terms of `each` (so you're
|
884
|
+
adding a level of indirection), but with a twist—`for` doesn't
|
885
|
+
introduce a new scope (unlike `each`) and variables defined in its block
|
886
|
+
will be visible outside it.
|
887
|
+
<sup>[[link](#no-for-loops)]</sup>
|
888
|
+
|
889
|
+
```Ruby
|
890
|
+
arr = [1, 2, 3]
|
891
|
+
|
892
|
+
# bad
|
893
|
+
for elem in arr do
|
894
|
+
puts elem
|
895
|
+
end
|
896
|
+
|
897
|
+
# note that elem is accessible outside of the for loop
|
898
|
+
elem # => 3
|
899
|
+
|
900
|
+
# good
|
901
|
+
arr.each { |elem| puts elem }
|
902
|
+
|
903
|
+
# elem is not accessible outside each's block
|
904
|
+
elem # => NameError: undefined local variable or method `elem'
|
905
|
+
```
|
906
|
+
|
907
|
+
* <a name="no-then"></a>
|
908
|
+
Do not use `then` for multi-line `if`/`unless`.
|
909
|
+
<sup>[[link](#no-then)]</sup>
|
910
|
+
|
911
|
+
```Ruby
|
912
|
+
# bad
|
913
|
+
if some_condition then
|
914
|
+
# body omitted
|
915
|
+
end
|
916
|
+
|
917
|
+
# good
|
918
|
+
if some_condition
|
919
|
+
# body omitted
|
920
|
+
end
|
921
|
+
```
|
922
|
+
|
923
|
+
* <a name="same-line-condition"></a>
|
924
|
+
Always put the condition on the same line as the `if`/`unless` in a
|
925
|
+
multi-line conditional.
|
926
|
+
<sup>[[link](#same-line-condition)]</sup>
|
927
|
+
|
928
|
+
```Ruby
|
929
|
+
# bad
|
930
|
+
if
|
931
|
+
some_condition
|
932
|
+
do_something
|
933
|
+
do_something_else
|
934
|
+
end
|
935
|
+
|
936
|
+
# good
|
937
|
+
if some_condition
|
938
|
+
do_something
|
939
|
+
do_something_else
|
940
|
+
end
|
941
|
+
```
|
942
|
+
|
943
|
+
* <a name="ternary-operator"></a>
|
944
|
+
Favor the ternary operator(`?:`) over `if/then/else/end` constructs.
|
945
|
+
It's more common and obviously more concise.
|
946
|
+
<sup>[[link](#ternary-operator)]</sup>
|
947
|
+
|
948
|
+
```Ruby
|
949
|
+
# bad
|
950
|
+
result = if some_condition then something else something_else end
|
951
|
+
|
952
|
+
# good
|
953
|
+
result = some_condition ? something : something_else
|
954
|
+
```
|
955
|
+
|
956
|
+
* <a name="no-nested-ternary"></a>
|
957
|
+
Use one expression per branch in a ternary operator. This
|
958
|
+
also means that ternary operators must not be nested. Prefer
|
959
|
+
`if/else` constructs in these cases.
|
960
|
+
<sup>[[link](#no-nested-ternary)]</sup>
|
961
|
+
|
962
|
+
```Ruby
|
963
|
+
# bad
|
964
|
+
some_condition ? (nested_condition ? nested_something : nested_something_else) : something_else
|
965
|
+
|
966
|
+
# good
|
967
|
+
if some_condition
|
968
|
+
nested_condition ? nested_something : nested_something_else
|
969
|
+
else
|
970
|
+
something_else
|
971
|
+
end
|
972
|
+
```
|
973
|
+
|
974
|
+
* <a name="no-semicolon-ifs"></a>
|
975
|
+
Do not use `if x; ...`. Use the ternary
|
976
|
+
operator instead.
|
977
|
+
<sup>[[link](#no-semicolon-ifs)]</sup>
|
978
|
+
|
979
|
+
```Ruby
|
980
|
+
# bad
|
981
|
+
result = if some_condition; something else something_else end
|
982
|
+
|
983
|
+
# good
|
984
|
+
result = some_condition ? something : something_else
|
985
|
+
```
|
986
|
+
|
987
|
+
* <a name="use-if-case-returns"></a>
|
988
|
+
Leverage the fact that `if` and `case` are expressions which return a
|
989
|
+
result.
|
990
|
+
<sup>[[link](#use-if-case-returns)]</sup>
|
991
|
+
|
992
|
+
```Ruby
|
993
|
+
# bad
|
994
|
+
if condition
|
995
|
+
result = x
|
996
|
+
else
|
997
|
+
result = y
|
998
|
+
end
|
999
|
+
|
1000
|
+
# good
|
1001
|
+
result =
|
1002
|
+
if condition
|
1003
|
+
x
|
1004
|
+
else
|
1005
|
+
y
|
1006
|
+
end
|
1007
|
+
```
|
1008
|
+
|
1009
|
+
* <a name="one-line-cases"></a>
|
1010
|
+
Use `when x then ...` for one-line cases. The alternative syntax `when x:
|
1011
|
+
...` has been removed as of Ruby 1.9.
|
1012
|
+
<sup>[[link](#one-line-cases)]</sup>
|
1013
|
+
|
1014
|
+
* <a name="no-when-semicolons"></a>
|
1015
|
+
Do not use `when x; ...`. See the previous rule.
|
1016
|
+
<sup>[[link](#no-when-semicolons)]</sup>
|
1017
|
+
|
1018
|
+
* <a name="bang-not-not"></a>
|
1019
|
+
Use `!` instead of `not`.
|
1020
|
+
<sup>[[link](#bang-not-not)]</sup>
|
1021
|
+
|
1022
|
+
```Ruby
|
1023
|
+
# bad - parentheses are required because of op precedence
|
1024
|
+
x = (not something)
|
1025
|
+
|
1026
|
+
# good
|
1027
|
+
x = !something
|
1028
|
+
```
|
1029
|
+
|
1030
|
+
* <a name="no-bang-bang"></a>
|
1031
|
+
Avoid the use of `!!`.
|
1032
|
+
<sup>[[link](#no-bang-bang)]</sup>
|
1033
|
+
|
1034
|
+
`!!` converts a value to boolean, but you don't need this explicit
|
1035
|
+
conversion in the condition of a control expression; using it only
|
1036
|
+
obscures your intention. If you want to do a `nil` check, use `nil?`
|
1037
|
+
instead.
|
1038
|
+
|
1039
|
+
```Ruby
|
1040
|
+
# bad
|
1041
|
+
x = 'test'
|
1042
|
+
# obscure nil check
|
1043
|
+
if !!x
|
1044
|
+
# body omitted
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
# good
|
1048
|
+
x = 'test'
|
1049
|
+
if x
|
1050
|
+
# body omitted
|
1051
|
+
end
|
1052
|
+
```
|
1053
|
+
|
1054
|
+
* <a name="no-and-or-or"></a>
|
1055
|
+
The `and` and `or` keywords are banned. The minimal added readability is just
|
1056
|
+
not worth the high probability of introducing subtle bugs. For boolean
|
1057
|
+
expressions, always use `&&` and `||` instead. For flow control, use
|
1058
|
+
`if` and `unless`; `&&` and `||` are also acceptable but less clear.
|
1059
|
+
<sup>[[link](#no-and-or-or)]</sup>
|
1060
|
+
|
1061
|
+
```Ruby
|
1062
|
+
# bad
|
1063
|
+
# boolean expression
|
1064
|
+
ok = got_needed_arguments and arguments_are_valid
|
1065
|
+
|
1066
|
+
# control flow
|
1067
|
+
document.save or fail(RuntimeError, "Failed to save document!")
|
1068
|
+
|
1069
|
+
# good
|
1070
|
+
# boolean expression
|
1071
|
+
ok = got_needed_arguments && arguments_are_valid
|
1072
|
+
|
1073
|
+
# control flow
|
1074
|
+
fail(RuntimeError, "Failed to save document!") unless document.save
|
1075
|
+
|
1076
|
+
# ok
|
1077
|
+
# control flow
|
1078
|
+
document.save || fail(RuntimeError, "Failed to save document!")
|
1079
|
+
```
|
1080
|
+
|
1081
|
+
* <a name="no-multiline-ternary"></a>
|
1082
|
+
Avoid multi-line `?:` (the ternary operator); use `if`/`unless` instead.
|
1083
|
+
<sup>[[link](#no-multiline-ternary)]</sup>
|
1084
|
+
|
1085
|
+
* <a name="if-as-a-modifier"></a>
|
1086
|
+
Favor modifier `if`/`unless` usage when you have a single-line body. Another
|
1087
|
+
good alternative is the usage of control flow `&&`/`||`.
|
1088
|
+
<sup>[[link](#if-as-a-modifier)]</sup>
|
1089
|
+
|
1090
|
+
```Ruby
|
1091
|
+
# bad
|
1092
|
+
if some_condition
|
1093
|
+
do_something
|
1094
|
+
end
|
1095
|
+
|
1096
|
+
# good
|
1097
|
+
do_something if some_condition
|
1098
|
+
|
1099
|
+
# another good option
|
1100
|
+
some_condition && do_something
|
1101
|
+
```
|
1102
|
+
|
1103
|
+
* <a name="no-multiline-if-modifiers"></a>
|
1104
|
+
Avoid modifier `if`/`unless` usage at the end of a non-trivial multi-line
|
1105
|
+
block.
|
1106
|
+
<sup>[[link](#no-multiline-if-modifiers)]</sup>
|
1107
|
+
|
1108
|
+
```Ruby
|
1109
|
+
# bad
|
1110
|
+
10.times do
|
1111
|
+
# multi-line body omitted
|
1112
|
+
end if some_condition
|
1113
|
+
|
1114
|
+
# good
|
1115
|
+
if some_condition
|
1116
|
+
10.times do
|
1117
|
+
# multi-line body omitted
|
1118
|
+
end
|
1119
|
+
end
|
1120
|
+
```
|
1121
|
+
|
1122
|
+
* <a name="no-nested-modifiers"></a>
|
1123
|
+
Avoid nested modifier `if`/`unless`/`while`/`until` usage. Favor `&&`/`||` if
|
1124
|
+
appropriate.
|
1125
|
+
<sup>[[link](#no-nested-modifiers)]</sup>
|
1126
|
+
|
1127
|
+
```Ruby
|
1128
|
+
# bad
|
1129
|
+
do_something if other_condition if some_condition
|
1130
|
+
|
1131
|
+
# good
|
1132
|
+
do_something if some_condition && other_condition
|
1133
|
+
```
|
1134
|
+
|
1135
|
+
* <a name="unless-for-negatives"></a>
|
1136
|
+
Favor `unless` over `if` for negative conditions (or control flow `||`).
|
1137
|
+
<sup>[[link](#unless-for-negatives)]</sup>
|
1138
|
+
|
1139
|
+
```Ruby
|
1140
|
+
# bad
|
1141
|
+
do_something if !some_condition
|
1142
|
+
|
1143
|
+
# bad
|
1144
|
+
do_something if not some_condition
|
1145
|
+
|
1146
|
+
# good
|
1147
|
+
do_something unless some_condition
|
1148
|
+
|
1149
|
+
# another good option
|
1150
|
+
some_condition || do_something
|
1151
|
+
```
|
1152
|
+
|
1153
|
+
* <a name="no-else-with-unless"></a>
|
1154
|
+
Do not use `unless` with `else`. Rewrite these with the positive case first.
|
1155
|
+
<sup>[[link](#no-else-with-unless)]</sup>
|
1156
|
+
|
1157
|
+
```Ruby
|
1158
|
+
# bad
|
1159
|
+
unless success?
|
1160
|
+
puts 'failure'
|
1161
|
+
else
|
1162
|
+
puts 'success'
|
1163
|
+
end
|
1164
|
+
|
1165
|
+
# good
|
1166
|
+
if success?
|
1167
|
+
puts 'success'
|
1168
|
+
else
|
1169
|
+
puts 'failure'
|
1170
|
+
end
|
1171
|
+
```
|
1172
|
+
|
1173
|
+
* <a name="no-parens-around-condition"></a>
|
1174
|
+
Don't use parentheses around the condition of a control expression.
|
1175
|
+
<sup>[[link](#no-parens-around-condition)]</sup>
|
1176
|
+
|
1177
|
+
```Ruby
|
1178
|
+
# bad
|
1179
|
+
if (x > 10)
|
1180
|
+
# body omitted
|
1181
|
+
end
|
1182
|
+
|
1183
|
+
# good
|
1184
|
+
if x > 10
|
1185
|
+
# body omitted
|
1186
|
+
end
|
1187
|
+
```
|
1188
|
+
|
1189
|
+
Note that there is an exception to this rule, namely [safe assignment in
|
1190
|
+
condition](#safe-assignment-in-condition).
|
1191
|
+
|
1192
|
+
* <a name="no-multiline-while-do"></a>
|
1193
|
+
Do not use `while/until condition do` for multi-line `while/until`.
|
1194
|
+
<sup>[[link](#no-multiline-while-do)]</sup>
|
1195
|
+
|
1196
|
+
```Ruby
|
1197
|
+
# bad
|
1198
|
+
while x > 5 do
|
1199
|
+
# body omitted
|
1200
|
+
end
|
1201
|
+
|
1202
|
+
until x > 5 do
|
1203
|
+
# body omitted
|
1204
|
+
end
|
1205
|
+
|
1206
|
+
# good
|
1207
|
+
while x > 5
|
1208
|
+
# body omitted
|
1209
|
+
end
|
1210
|
+
|
1211
|
+
until x > 5
|
1212
|
+
# body omitted
|
1213
|
+
end
|
1214
|
+
```
|
1215
|
+
|
1216
|
+
* <a name="while-as-a-modifier"></a>
|
1217
|
+
Favor modifier `while/until` usage when you have a single-line body.
|
1218
|
+
<sup>[[link](#while-as-a-modifier)]</sup>
|
1219
|
+
|
1220
|
+
```Ruby
|
1221
|
+
# bad
|
1222
|
+
while some_condition
|
1223
|
+
do_something
|
1224
|
+
end
|
1225
|
+
|
1226
|
+
# good
|
1227
|
+
do_something while some_condition
|
1228
|
+
```
|
1229
|
+
|
1230
|
+
* <a name="until-for-negatives"></a>
|
1231
|
+
Favor `until` over `while` for negative conditions.
|
1232
|
+
<sup>[[link](#until-for-negatives)]</sup>
|
1233
|
+
|
1234
|
+
```Ruby
|
1235
|
+
# bad
|
1236
|
+
do_something while !some_condition
|
1237
|
+
|
1238
|
+
# good
|
1239
|
+
do_something until some_condition
|
1240
|
+
```
|
1241
|
+
|
1242
|
+
* <a name="infinite-loop"></a>
|
1243
|
+
Use `Kernel#loop` instead of `while/until` when you need an infinite loop.
|
1244
|
+
<sup>[[link](#infinite-loop)]</sup>
|
1245
|
+
|
1246
|
+
```ruby
|
1247
|
+
# bad
|
1248
|
+
while true
|
1249
|
+
do_something
|
1250
|
+
end
|
1251
|
+
|
1252
|
+
until false
|
1253
|
+
do_something
|
1254
|
+
end
|
1255
|
+
|
1256
|
+
# good
|
1257
|
+
loop do
|
1258
|
+
do_something
|
1259
|
+
end
|
1260
|
+
```
|
1261
|
+
|
1262
|
+
* <a name="loop-with-break"></a>
|
1263
|
+
Use `Kernel#loop` with `break` rather than `begin/end/until` or
|
1264
|
+
`begin/end/while` for post-loop tests.
|
1265
|
+
<sup>[[link](#loop-with-break)]</sup>
|
1266
|
+
|
1267
|
+
```Ruby
|
1268
|
+
# bad
|
1269
|
+
begin
|
1270
|
+
puts val
|
1271
|
+
val += 1
|
1272
|
+
end while val < 0
|
1273
|
+
|
1274
|
+
# good
|
1275
|
+
loop do
|
1276
|
+
puts val
|
1277
|
+
val += 1
|
1278
|
+
break unless val < 0
|
1279
|
+
end
|
1280
|
+
```
|
1281
|
+
|
1282
|
+
* <a name="no-braces-opts-hash"></a>
|
1283
|
+
Omit the outer braces around an implicit options hash.
|
1284
|
+
<sup>[[link](#no-braces-opts-hash)]</sup>
|
1285
|
+
|
1286
|
+
```Ruby
|
1287
|
+
# bad
|
1288
|
+
user.set({ name: 'John', age: 45, permissions: { read: true } })
|
1289
|
+
|
1290
|
+
# good
|
1291
|
+
user.set(name: 'John', age: 45, permissions: { read: true })
|
1292
|
+
```
|
1293
|
+
|
1294
|
+
* <a name="no-dsl-decorating"></a>
|
1295
|
+
Omit both the outer braces and parentheses for methods that are part of an
|
1296
|
+
internal DSL.
|
1297
|
+
<sup>[[link](#no-dsl-decorating)]</sup>
|
1298
|
+
|
1299
|
+
```Ruby
|
1300
|
+
class Person < ActiveRecord::Base
|
1301
|
+
# bad
|
1302
|
+
validates(:name, { presence: true, length: { within: 1..10 } })
|
1303
|
+
|
1304
|
+
# good
|
1305
|
+
validates :name, presence: true, length: { within: 1..10 }
|
1306
|
+
end
|
1307
|
+
```
|
1308
|
+
|
1309
|
+
* <a name="single-action-blocks"></a>
|
1310
|
+
Use the proc invocation shorthand when the invoked method is the only operation of a block.
|
1311
|
+
<sup>[[link](#single-action-blocks)]</sup>
|
1312
|
+
|
1313
|
+
```Ruby
|
1314
|
+
# bad
|
1315
|
+
names.map { |name| name.upcase }
|
1316
|
+
|
1317
|
+
# good
|
1318
|
+
names.map(&:upcase)
|
1319
|
+
```
|
1320
|
+
|
1321
|
+
* <a name="single-line-blocks"></a>
|
1322
|
+
Prefer `{...}` over `do...end` for single-line blocks. Avoid using `{...}`
|
1323
|
+
for multi-line blocks (multi-line chaining is always ugly), except in
|
1324
|
+
RSpec source files, e.g., when using `before`, `let`, `subject`, etc. Always use
|
1325
|
+
`do...end` for "control flow" and "method definitions" (e.g. in Rakefiles and
|
1326
|
+
certain DSLs). Avoid `do...end` when chaining.
|
1327
|
+
<sup>[[link](#single-line-blocks)]</sup>
|
1328
|
+
|
1329
|
+
```Ruby
|
1330
|
+
names = %w[Bozhidar Steve Sarah]
|
1331
|
+
|
1332
|
+
# bad
|
1333
|
+
names.each do |name|
|
1334
|
+
puts name
|
1335
|
+
end
|
1336
|
+
|
1337
|
+
# good
|
1338
|
+
names.each { |name| puts name }
|
1339
|
+
|
1340
|
+
# bad
|
1341
|
+
names.select do |name|
|
1342
|
+
name.start_with?('S')
|
1343
|
+
end.map { |name| name.upcase }
|
1344
|
+
|
1345
|
+
# good
|
1346
|
+
names.select { |name| name.start_with?('S') }.map(&:upcase)
|
1347
|
+
```
|
1348
|
+
|
1349
|
+
Some will argue that multi-line chaining would look OK with the use of {...},
|
1350
|
+
but they should ask themselves—is this code really readable and can the
|
1351
|
+
blocks' contents be extracted into nifty methods?
|
1352
|
+
|
1353
|
+
* <a name="block-argument"></a>
|
1354
|
+
Consider using explicit block argument to avoid writing block literal that
|
1355
|
+
just passes its arguments to another block. Beware of the performance impact,
|
1356
|
+
though, as the block gets converted to a Proc.
|
1357
|
+
<sup>[[link](#block-argument)]</sup>
|
1358
|
+
|
1359
|
+
```Ruby
|
1360
|
+
require 'tempfile'
|
1361
|
+
|
1362
|
+
# bad
|
1363
|
+
def with_tmp_dir
|
1364
|
+
Dir.mktmpdir do |tmp_dir|
|
1365
|
+
Dir.chdir(tmp_dir) { |dir| yield dir } # block just passes arguments
|
1366
|
+
end
|
1367
|
+
end
|
1368
|
+
|
1369
|
+
# good
|
1370
|
+
def with_tmp_dir(&block)
|
1371
|
+
Dir.mktmpdir do |tmp_dir|
|
1372
|
+
Dir.chdir(tmp_dir, &block)
|
1373
|
+
end
|
1374
|
+
end
|
1375
|
+
|
1376
|
+
with_tmp_dir do |dir|
|
1377
|
+
puts "dir is accessible as a parameter and pwd is set: #{dir}"
|
1378
|
+
end
|
1379
|
+
```
|
1380
|
+
|
1381
|
+
* <a name="no-explicit-return"></a>
|
1382
|
+
Avoid `return` where not required for flow of control.
|
1383
|
+
<sup>[[link](#no-explicit-return)]</sup>
|
1384
|
+
|
1385
|
+
```Ruby
|
1386
|
+
# bad
|
1387
|
+
def some_method(some_arr)
|
1388
|
+
return some_arr.size
|
1389
|
+
end
|
1390
|
+
|
1391
|
+
# good
|
1392
|
+
def some_method(some_arr)
|
1393
|
+
some_arr.size
|
1394
|
+
end
|
1395
|
+
```
|
1396
|
+
|
1397
|
+
* <a name="no-self-unless-required"></a>
|
1398
|
+
Avoid `self` where not required. (It is only required when calling a self
|
1399
|
+
write accessor, methods named after reserved words, or overloadable operators.)
|
1400
|
+
<sup>[[link](#no-self-unless-required)]</sup>
|
1401
|
+
|
1402
|
+
```Ruby
|
1403
|
+
# bad
|
1404
|
+
def ready?
|
1405
|
+
if self.last_reviewed_at > self.last_updated_at
|
1406
|
+
self.worker.update(self.content, self.options)
|
1407
|
+
self.status = :in_progress
|
1408
|
+
end
|
1409
|
+
self.status == :verified
|
1410
|
+
end
|
1411
|
+
|
1412
|
+
# good
|
1413
|
+
def ready?
|
1414
|
+
if last_reviewed_at > last_updated_at
|
1415
|
+
worker.update(content, options)
|
1416
|
+
self.status = :in_progress
|
1417
|
+
end
|
1418
|
+
status == :verified
|
1419
|
+
end
|
1420
|
+
```
|
1421
|
+
|
1422
|
+
* <a name="no-shadowing"></a>
|
1423
|
+
As a corollary, avoid shadowing methods with local variables unless they are
|
1424
|
+
both equivalent.
|
1425
|
+
<sup>[[link](#no-shadowing)]</sup>
|
1426
|
+
|
1427
|
+
```Ruby
|
1428
|
+
class Foo
|
1429
|
+
attr_accessor :options
|
1430
|
+
|
1431
|
+
# ok
|
1432
|
+
def initialize(options)
|
1433
|
+
self.options = options
|
1434
|
+
# both options and self.options are equivalent here
|
1435
|
+
end
|
1436
|
+
|
1437
|
+
# bad
|
1438
|
+
def do_something(options = {})
|
1439
|
+
unless options[:when] == :later
|
1440
|
+
output(self.options[:message])
|
1441
|
+
end
|
1442
|
+
end
|
1443
|
+
|
1444
|
+
# good
|
1445
|
+
def do_something(params = {})
|
1446
|
+
unless params[:when] == :later
|
1447
|
+
output(options[:message])
|
1448
|
+
end
|
1449
|
+
end
|
1450
|
+
end
|
1451
|
+
```
|
1452
|
+
|
1453
|
+
* <a name="safe-assignment-in-condition"></a>
|
1454
|
+
Don't use the return value of `=` (an assignment) in conditional expressions
|
1455
|
+
unless the assignment is wrapped in parentheses. This is a fairly popular
|
1456
|
+
idiom among Rubyists that's sometimes referred to as *safe assignment in
|
1457
|
+
condition*.
|
1458
|
+
<sup>[[link](#safe-assignment-in-condition)]</sup>
|
1459
|
+
|
1460
|
+
```Ruby
|
1461
|
+
# bad (+ a warning)
|
1462
|
+
if v = array.grep(/foo/)
|
1463
|
+
do_something(v)
|
1464
|
+
# some code
|
1465
|
+
end
|
1466
|
+
|
1467
|
+
# good (MRI would still complain, but RuboCop won't)
|
1468
|
+
if (v = array.grep(/foo/))
|
1469
|
+
do_something(v)
|
1470
|
+
# some code
|
1471
|
+
end
|
1472
|
+
|
1473
|
+
# good
|
1474
|
+
v = array.grep(/foo/)
|
1475
|
+
if v
|
1476
|
+
do_something(v)
|
1477
|
+
# some code
|
1478
|
+
end
|
1479
|
+
```
|
1480
|
+
|
1481
|
+
* <a name="self-assignment"></a>
|
1482
|
+
Use shorthand self assignment operators whenever applicable.
|
1483
|
+
<sup>[[link](#self-assignment)]</sup>
|
1484
|
+
|
1485
|
+
```Ruby
|
1486
|
+
# bad
|
1487
|
+
x = x + y
|
1488
|
+
x = x * y
|
1489
|
+
x = x**y
|
1490
|
+
x = x / y
|
1491
|
+
x = x || y
|
1492
|
+
x = x && y
|
1493
|
+
|
1494
|
+
# good
|
1495
|
+
x += y
|
1496
|
+
x *= y
|
1497
|
+
x **= y
|
1498
|
+
x /= y
|
1499
|
+
x ||= y
|
1500
|
+
x &&= y
|
1501
|
+
```
|
1502
|
+
|
1503
|
+
* <a name="double-pipe-for-uninit"></a>
|
1504
|
+
Use `||=` to initialize variables only if they're not already initialized.
|
1505
|
+
<sup>[[link](#double-pipe-for-uninit)]</sup>
|
1506
|
+
|
1507
|
+
```Ruby
|
1508
|
+
# bad
|
1509
|
+
name = name ? name : 'Bozhidar'
|
1510
|
+
|
1511
|
+
# bad
|
1512
|
+
name = 'Bozhidar' unless name
|
1513
|
+
|
1514
|
+
# good - set name to 'Bozhidar', only if it's nil or false
|
1515
|
+
name ||= 'Bozhidar'
|
1516
|
+
```
|
1517
|
+
|
1518
|
+
* <a name="no-double-pipes-for-bools"></a>
|
1519
|
+
Don't use `||=` to initialize boolean variables. (Consider what would happen
|
1520
|
+
if the current value happened to be `false`.)
|
1521
|
+
<sup>[[link](#no-double-pipes-for-bools)]</sup>
|
1522
|
+
|
1523
|
+
```Ruby
|
1524
|
+
# bad - would set enabled to true even if it was false
|
1525
|
+
enabled ||= true
|
1526
|
+
|
1527
|
+
# good
|
1528
|
+
enabled = true if enabled.nil?
|
1529
|
+
```
|
1530
|
+
|
1531
|
+
* <a name="double-amper-preprocess"></a>
|
1532
|
+
Use `&&=` to preprocess variables that may or may not exist. Using `&&=`
|
1533
|
+
will change the value only if it exists, removing the need to check its
|
1534
|
+
existence with `if`.
|
1535
|
+
<sup>[[link](#double-amper-preprocess)]</sup>
|
1536
|
+
|
1537
|
+
```Ruby
|
1538
|
+
# bad
|
1539
|
+
if something
|
1540
|
+
something = something.downcase
|
1541
|
+
end
|
1542
|
+
|
1543
|
+
# bad
|
1544
|
+
something = something ? something.downcase : nil
|
1545
|
+
|
1546
|
+
# ok
|
1547
|
+
something = something.downcase if something
|
1548
|
+
|
1549
|
+
# good
|
1550
|
+
something = something && something.downcase
|
1551
|
+
|
1552
|
+
# better
|
1553
|
+
something &&= something.downcase
|
1554
|
+
```
|
1555
|
+
|
1556
|
+
* <a name="no-case-equality"></a>
|
1557
|
+
Avoid explicit use of the case equality operator `===`. As its name implies
|
1558
|
+
it is meant to be used implicitly by `case` expressions and outside of them it
|
1559
|
+
yields some pretty confusing code.
|
1560
|
+
<sup>[[link](#no-case-equality)]</sup>
|
1561
|
+
|
1562
|
+
```Ruby
|
1563
|
+
# bad
|
1564
|
+
Array === something
|
1565
|
+
(1..100) === 7
|
1566
|
+
/something/ === some_string
|
1567
|
+
|
1568
|
+
# good
|
1569
|
+
something.is_a?(Array)
|
1570
|
+
(1..100).include?(7)
|
1571
|
+
some_string =~ /something/
|
1572
|
+
```
|
1573
|
+
|
1574
|
+
* <a name="eql"></a>
|
1575
|
+
Do not use `eql?` when using `==` will do. The stricter comparison semantics
|
1576
|
+
provided by `eql?` are rarely needed in practice.
|
1577
|
+
<sup>[[link](#eql)]</sup>
|
1578
|
+
|
1579
|
+
```Ruby
|
1580
|
+
# bad - eql? is the same as == for strings
|
1581
|
+
'ruby'.eql? some_str
|
1582
|
+
|
1583
|
+
# good
|
1584
|
+
'ruby' == some_str
|
1585
|
+
1.0.eql? x # eql? makes sense here if want to differentiate between Integer and Float 1
|
1586
|
+
```
|
1587
|
+
|
1588
|
+
* <a name="no-cryptic-perlisms"></a>
|
1589
|
+
Avoid using Perl-style special variables (like `$:`, `$;`, etc. ). They are
|
1590
|
+
quite cryptic and their use in anything but one-liner scripts is discouraged.
|
1591
|
+
Use the human-friendly aliases provided by the `English` library.
|
1592
|
+
<sup>[[link](#no-cryptic-perlisms)]</sup>
|
1593
|
+
|
1594
|
+
```Ruby
|
1595
|
+
# bad
|
1596
|
+
$:.unshift File.dirname(__FILE__)
|
1597
|
+
|
1598
|
+
# good
|
1599
|
+
require 'English'
|
1600
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
1601
|
+
```
|
1602
|
+
|
1603
|
+
* <a name="parens-no-spaces"></a>
|
1604
|
+
Do not put a space between a method name and the opening parenthesis.
|
1605
|
+
<sup>[[link](#parens-no-spaces)]</sup>
|
1606
|
+
|
1607
|
+
```Ruby
|
1608
|
+
# bad
|
1609
|
+
f (3 + 2) + 1
|
1610
|
+
|
1611
|
+
# good
|
1612
|
+
f(3 + 2) + 1
|
1613
|
+
```
|
1614
|
+
|
1615
|
+
* <a name="always-warn-at-runtime"></a>
|
1616
|
+
Always run the Ruby interpreter with the `-w` option so it will warn you if
|
1617
|
+
you forget either of the rules above!
|
1618
|
+
<sup>[[link](#always-warn-at-runtime)]</sup>
|
1619
|
+
|
1620
|
+
* <a name="no-nested-methods"></a>
|
1621
|
+
Do not use nested method definitions, use lambda instead.
|
1622
|
+
Nested method definitions actually produce methods in the same scope
|
1623
|
+
(e.g. class) as the outer method. Furthermore, the "nested method" will be
|
1624
|
+
redefined every time the method containing its definition is invoked.
|
1625
|
+
<sup>[[link](#no-nested-methods)]</sup>
|
1626
|
+
|
1627
|
+
```Ruby
|
1628
|
+
# bad
|
1629
|
+
def foo(x)
|
1630
|
+
def bar(y)
|
1631
|
+
# body omitted
|
1632
|
+
end
|
1633
|
+
|
1634
|
+
bar(x)
|
1635
|
+
end
|
1636
|
+
|
1637
|
+
# good - the same as the previous, but no bar redefinition on every foo call
|
1638
|
+
def bar(y)
|
1639
|
+
# body omitted
|
1640
|
+
end
|
1641
|
+
|
1642
|
+
def foo(x)
|
1643
|
+
bar(x)
|
1644
|
+
end
|
1645
|
+
|
1646
|
+
# also good
|
1647
|
+
def foo(x)
|
1648
|
+
bar = ->(y) { ... }
|
1649
|
+
bar.call(x)
|
1650
|
+
end
|
1651
|
+
```
|
1652
|
+
|
1653
|
+
* <a name="lambda-multi-line"></a>
|
1654
|
+
Use the new lambda literal syntax for single line body blocks. Use the
|
1655
|
+
`lambda` method for multi-line blocks.
|
1656
|
+
<sup>[[link](#lambda-multi-line)]</sup>
|
1657
|
+
|
1658
|
+
```Ruby
|
1659
|
+
# bad
|
1660
|
+
l = lambda { |a, b| a + b }
|
1661
|
+
l.call(1, 2)
|
1662
|
+
|
1663
|
+
# correct, but looks extremely awkward
|
1664
|
+
l = ->(a, b) do
|
1665
|
+
tmp = a * 7
|
1666
|
+
tmp * b / 50
|
1667
|
+
end
|
1668
|
+
|
1669
|
+
# good
|
1670
|
+
l = ->(a, b) { a + b }
|
1671
|
+
l.call(1, 2)
|
1672
|
+
|
1673
|
+
l = lambda do |a, b|
|
1674
|
+
tmp = a * 7
|
1675
|
+
tmp * b / 50
|
1676
|
+
end
|
1677
|
+
```
|
1678
|
+
|
1679
|
+
* <a name="stabby-lambda-with-args"></a>
|
1680
|
+
Don't omit the parameter parentheses when defining a stabby lambda with
|
1681
|
+
parameters.
|
1682
|
+
<sup>[[link](#stabby-lambda-with-args)]</sup>
|
1683
|
+
|
1684
|
+
```Ruby
|
1685
|
+
# bad
|
1686
|
+
l = ->x, y { something(x, y) }
|
1687
|
+
|
1688
|
+
# good
|
1689
|
+
l = ->(x, y) { something(x, y) }
|
1690
|
+
```
|
1691
|
+
|
1692
|
+
* <a name="stabby-lambda-no-args"></a>
|
1693
|
+
Omit the parameter parentheses when defining a stabby lambda with
|
1694
|
+
no parameters.
|
1695
|
+
<sup>[[link](#stabby-lambda-no-args)]</sup>
|
1696
|
+
|
1697
|
+
```Ruby
|
1698
|
+
# bad
|
1699
|
+
l = ->() { something }
|
1700
|
+
|
1701
|
+
# good
|
1702
|
+
l = -> { something }
|
1703
|
+
```
|
1704
|
+
|
1705
|
+
* <a name="proc"></a>
|
1706
|
+
Prefer `proc` over `Proc.new`.
|
1707
|
+
<sup>[[link](#proc)]</sup>
|
1708
|
+
|
1709
|
+
```Ruby
|
1710
|
+
# bad
|
1711
|
+
p = Proc.new { |n| puts n }
|
1712
|
+
|
1713
|
+
# good
|
1714
|
+
p = proc { |n| puts n }
|
1715
|
+
```
|
1716
|
+
|
1717
|
+
* <a name="proc-call"></a>
|
1718
|
+
Prefer `proc.call()` over `proc[]` or `proc.()` for both lambdas and procs.
|
1719
|
+
<sup>[[link](#proc-call)]</sup>
|
1720
|
+
|
1721
|
+
```Ruby
|
1722
|
+
# bad - looks similar to Enumeration access
|
1723
|
+
l = ->(v) { puts v }
|
1724
|
+
l[1]
|
1725
|
+
|
1726
|
+
# also bad - uncommon syntax
|
1727
|
+
l = ->(v) { puts v }
|
1728
|
+
l.(1)
|
1729
|
+
|
1730
|
+
# good
|
1731
|
+
l = ->(v) { puts v }
|
1732
|
+
l.call(1)
|
1733
|
+
```
|
1734
|
+
|
1735
|
+
* <a name="underscore-unused-vars"></a>
|
1736
|
+
Prefix with `_` unused block parameters and local variables. It's also
|
1737
|
+
acceptable to use just `_` (although it's a bit less descriptive). This
|
1738
|
+
convention is recognized by the Ruby interpreter and tools like RuboCop and
|
1739
|
+
will suppress their unused variable warnings.
|
1740
|
+
<sup>[[link](#underscore-unused-vars)]</sup>
|
1741
|
+
|
1742
|
+
```Ruby
|
1743
|
+
# bad
|
1744
|
+
result = hash.map { |k, v| v + 1 }
|
1745
|
+
|
1746
|
+
def something(x)
|
1747
|
+
unused_var, used_var = something_else(x)
|
1748
|
+
# some code
|
1749
|
+
end
|
1750
|
+
|
1751
|
+
# good
|
1752
|
+
result = hash.map { |_k, v| v + 1 }
|
1753
|
+
|
1754
|
+
def something(x)
|
1755
|
+
_unused_var, used_var = something_else(x)
|
1756
|
+
# some code
|
1757
|
+
end
|
1758
|
+
|
1759
|
+
# good
|
1760
|
+
result = hash.map { |_, v| v + 1 }
|
1761
|
+
|
1762
|
+
def something(x)
|
1763
|
+
_, used_var = something_else(x)
|
1764
|
+
# some code
|
1765
|
+
end
|
1766
|
+
```
|
1767
|
+
|
1768
|
+
* <a name="global-stdout"></a>
|
1769
|
+
Use `$stdout/$stderr/$stdin` instead of `STDOUT/STDERR/STDIN`.
|
1770
|
+
`STDOUT/STDERR/STDIN` are constants, and while you can actually reassign
|
1771
|
+
(possibly to redirect some stream) constants in Ruby, you'll get an
|
1772
|
+
interpreter warning if you do so.
|
1773
|
+
<sup>[[link](#global-stdout)]</sup>
|
1774
|
+
|
1775
|
+
* <a name="warn"></a>
|
1776
|
+
Use `warn` instead of `$stderr.puts`. Apart from being more concise and
|
1777
|
+
clear, `warn` allows you to suppress warnings if you need to (by setting the
|
1778
|
+
warn level to 0 via `-W0`).
|
1779
|
+
<sup>[[link](#warn)]</sup>
|
1780
|
+
|
1781
|
+
* <a name="sprintf"></a>
|
1782
|
+
Favor the use of `sprintf` and its alias `format` over the fairly cryptic
|
1783
|
+
`String#%` method.
|
1784
|
+
<sup>[[link](#sprintf)]</sup>
|
1785
|
+
|
1786
|
+
```Ruby
|
1787
|
+
# bad
|
1788
|
+
'%d %d' % [20, 10]
|
1789
|
+
# => '20 10'
|
1790
|
+
|
1791
|
+
# good
|
1792
|
+
sprintf('%d %d', 20, 10)
|
1793
|
+
# => '20 10'
|
1794
|
+
|
1795
|
+
# good
|
1796
|
+
sprintf('%{first} %{second}', first: 20, second: 10)
|
1797
|
+
# => '20 10'
|
1798
|
+
|
1799
|
+
format('%d %d', 20, 10)
|
1800
|
+
# => '20 10'
|
1801
|
+
|
1802
|
+
# good
|
1803
|
+
format('%{first} %{second}', first: 20, second: 10)
|
1804
|
+
# => '20 10'
|
1805
|
+
```
|
1806
|
+
|
1807
|
+
* <a name="array-join"></a>
|
1808
|
+
Favor the use of `Array#join` over the fairly cryptic `Array#*` with
|
1809
|
+
a string argument.
|
1810
|
+
<sup>[[link](#array-join)]</sup>
|
1811
|
+
|
1812
|
+
```Ruby
|
1813
|
+
# bad
|
1814
|
+
%w[one two three] * ', '
|
1815
|
+
# => 'one, two, three'
|
1816
|
+
|
1817
|
+
# good
|
1818
|
+
%w[one two three].join(', ')
|
1819
|
+
# => 'one, two, three'
|
1820
|
+
```
|
1821
|
+
|
1822
|
+
* <a name="array-coercion"></a>
|
1823
|
+
Use `Array()` instead of explicit `Array` check or `[*var]`, when dealing
|
1824
|
+
with a variable you want to treat as an Array, but you're not certain it's an
|
1825
|
+
array.
|
1826
|
+
<sup>[[link](#array-coercion)]</sup>
|
1827
|
+
|
1828
|
+
```Ruby
|
1829
|
+
# bad
|
1830
|
+
paths = [paths] unless paths.is_a? Array
|
1831
|
+
paths.each { |path| do_something(path) }
|
1832
|
+
|
1833
|
+
# bad (always creates a new Array instance)
|
1834
|
+
[*paths].each { |path| do_something(path) }
|
1835
|
+
|
1836
|
+
# good (and a bit more readable)
|
1837
|
+
Array(paths).each { |path| do_something(path) }
|
1838
|
+
```
|
1839
|
+
|
1840
|
+
* <a name="ranges-or-between"></a>
|
1841
|
+
Use ranges or `Comparable#between?` instead of complex comparison logic when
|
1842
|
+
possible.
|
1843
|
+
<sup>[[link](#ranges-or-between)]</sup>
|
1844
|
+
|
1845
|
+
```Ruby
|
1846
|
+
# bad
|
1847
|
+
do_something if x >= 1000 && x <= 2000
|
1848
|
+
|
1849
|
+
# good
|
1850
|
+
do_something if (1000..2000).include?(x)
|
1851
|
+
|
1852
|
+
# good
|
1853
|
+
do_something if x.between?(1000, 2000)
|
1854
|
+
```
|
1855
|
+
|
1856
|
+
* <a name="predicate-methods"></a>
|
1857
|
+
Favor the use of predicate methods to explicit comparisons with `==`.
|
1858
|
+
Numeric comparisons are OK.
|
1859
|
+
<sup>[[link](#predicate-methods)]</sup>
|
1860
|
+
|
1861
|
+
```Ruby
|
1862
|
+
# bad
|
1863
|
+
if x % 2 == 0
|
1864
|
+
end
|
1865
|
+
|
1866
|
+
if x % 2 == 1
|
1867
|
+
end
|
1868
|
+
|
1869
|
+
if x == nil
|
1870
|
+
end
|
1871
|
+
|
1872
|
+
# good
|
1873
|
+
if x.even?
|
1874
|
+
end
|
1875
|
+
|
1876
|
+
if x.odd?
|
1877
|
+
end
|
1878
|
+
|
1879
|
+
if x.nil?
|
1880
|
+
end
|
1881
|
+
|
1882
|
+
if x.zero?
|
1883
|
+
end
|
1884
|
+
|
1885
|
+
if x == 0
|
1886
|
+
end
|
1887
|
+
```
|
1888
|
+
|
1889
|
+
* <a name="no-non-nil-checks"></a>
|
1890
|
+
Don't do explicit non-`nil` checks unless you're dealing with boolean
|
1891
|
+
values.
|
1892
|
+
<sup>[[link](#no-non-nil-checks)]</sup>
|
1893
|
+
|
1894
|
+
```ruby
|
1895
|
+
# bad
|
1896
|
+
do_something if !something.nil?
|
1897
|
+
do_something if something != nil
|
1898
|
+
|
1899
|
+
# good
|
1900
|
+
do_something if something
|
1901
|
+
|
1902
|
+
# good - dealing with a boolean
|
1903
|
+
def value_set?
|
1904
|
+
!@some_boolean.nil?
|
1905
|
+
end
|
1906
|
+
```
|
1907
|
+
|
1908
|
+
* <a name="no-BEGIN-blocks"></a>
|
1909
|
+
Avoid the use of `BEGIN` blocks.
|
1910
|
+
<sup>[[link](#no-BEGIN-blocks)]</sup>
|
1911
|
+
|
1912
|
+
* <a name="no-END-blocks"></a>
|
1913
|
+
Do not use `END` blocks. Use `Kernel#at_exit` instead.
|
1914
|
+
<sup>[[link](#no-END-blocks)]</sup>
|
1915
|
+
|
1916
|
+
```ruby
|
1917
|
+
# bad
|
1918
|
+
END { puts 'Goodbye!' }
|
1919
|
+
|
1920
|
+
# good
|
1921
|
+
at_exit { puts 'Goodbye!' }
|
1922
|
+
```
|
1923
|
+
|
1924
|
+
* <a name="no-flip-flops"></a>
|
1925
|
+
Avoid the use of flip-flops.
|
1926
|
+
<sup>[[link](#no-flip-flops)]</sup>
|
1927
|
+
|
1928
|
+
* <a name="no-nested-conditionals"></a>
|
1929
|
+
Avoid use of nested conditionals for flow of control.
|
1930
|
+
<sup>[[link](#no-nested-conditionals)]</sup>
|
1931
|
+
|
1932
|
+
Prefer a guard clause when you can assert invalid data. A guard clause
|
1933
|
+
is a conditional statement at the top of a function that bails out as
|
1934
|
+
soon as it can.
|
1935
|
+
|
1936
|
+
```Ruby
|
1937
|
+
# bad
|
1938
|
+
def compute_thing(thing)
|
1939
|
+
if thing[:foo]
|
1940
|
+
update_with_bar(thing[:foo])
|
1941
|
+
if thing[:foo][:bar]
|
1942
|
+
partial_compute(thing)
|
1943
|
+
else
|
1944
|
+
re_compute(thing)
|
1945
|
+
end
|
1946
|
+
end
|
1947
|
+
end
|
1948
|
+
|
1949
|
+
# good
|
1950
|
+
def compute_thing(thing)
|
1951
|
+
return unless thing[:foo]
|
1952
|
+
update_with_bar(thing[:foo])
|
1953
|
+
return re_compute(thing) unless thing[:foo][:bar]
|
1954
|
+
partial_compute(thing)
|
1955
|
+
end
|
1956
|
+
```
|
1957
|
+
|
1958
|
+
Prefer `next` in loops instead of conditional blocks.
|
1959
|
+
|
1960
|
+
```Ruby
|
1961
|
+
# bad
|
1962
|
+
[0, 1, 2, 3].each do |item|
|
1963
|
+
if item > 1
|
1964
|
+
puts item
|
1965
|
+
end
|
1966
|
+
end
|
1967
|
+
|
1968
|
+
# good
|
1969
|
+
[0, 1, 2, 3].each do |item|
|
1970
|
+
next unless item > 1
|
1971
|
+
puts item
|
1972
|
+
end
|
1973
|
+
```
|
1974
|
+
|
1975
|
+
* <a name="map-find-select-reduce-size"></a>
|
1976
|
+
Prefer `map` over `collect`, `find` over `detect`, `select` over `find_all`,
|
1977
|
+
`reduce` over `inject` and `size` over `length`. This is not a hard
|
1978
|
+
requirement; if the use of the alias enhances readability, it's ok to use it.
|
1979
|
+
The rhyming methods are inherited from Smalltalk and are not common in other
|
1980
|
+
programming languages. The reason the use of `select` is encouraged over
|
1981
|
+
`find_all` is that it goes together nicely with `reject` and its name is
|
1982
|
+
pretty self-explanatory.
|
1983
|
+
<sup>[[link](#map-find-select-reduce-size)]</sup>
|
1984
|
+
|
1985
|
+
* <a name="count-vs-size"></a>
|
1986
|
+
Don't use `count` as a substitute for `size`. For `Enumerable` objects other
|
1987
|
+
than `Array` it will iterate the entire collection in order to determine its
|
1988
|
+
size.
|
1989
|
+
<sup>[[link](#count-vs-size)]</sup>
|
1990
|
+
|
1991
|
+
```Ruby
|
1992
|
+
# bad
|
1993
|
+
some_hash.count
|
1994
|
+
|
1995
|
+
# good
|
1996
|
+
some_hash.size
|
1997
|
+
```
|
1998
|
+
|
1999
|
+
* <a name="flat-map"></a>
|
2000
|
+
Use `flat_map` instead of `map` + `flatten`. This does not apply for arrays
|
2001
|
+
with a depth greater than 2, i.e. if `users.first.songs == ['a', ['b','c']]`,
|
2002
|
+
then use `map + flatten` rather than `flat_map`. `flat_map` flattens the
|
2003
|
+
array by 1, whereas `flatten` flattens it all the way.
|
2004
|
+
<sup>[[link](#flat-map)]</sup>
|
2005
|
+
|
2006
|
+
```Ruby
|
2007
|
+
# bad
|
2008
|
+
all_songs = users.map(&:songs).flatten.uniq
|
2009
|
+
|
2010
|
+
# good
|
2011
|
+
all_songs = users.flat_map(&:songs).uniq
|
2012
|
+
```
|
2013
|
+
|
2014
|
+
* <a name="reverse-each"></a>
|
2015
|
+
Prefer `reverse_each` to `reverse.each` because some classes that `include
|
2016
|
+
Enumerable` will provide an efficient implementation. Even in the worst case
|
2017
|
+
where a class does not provide a specialized implementation, the general
|
2018
|
+
implementation inherited from `Enumerable` will be at least as efficient as
|
2019
|
+
using `reverse.each`.
|
2020
|
+
<sup>[[link](#reverse-each)]</sup>
|
2021
|
+
|
2022
|
+
```Ruby
|
2023
|
+
# bad
|
2024
|
+
array.reverse.each { ... }
|
2025
|
+
|
2026
|
+
# good
|
2027
|
+
array.reverse_each { ... }
|
2028
|
+
```
|
2029
|
+
|
2030
|
+
## Naming
|
2031
|
+
|
2032
|
+
> The only real difficulties in programming are cache invalidation and
|
2033
|
+
> naming things. <br>
|
2034
|
+
> -- Phil Karlton
|
2035
|
+
|
2036
|
+
* <a name="english-identifiers"></a>
|
2037
|
+
Name identifiers in English.
|
2038
|
+
<sup>[[link](#english-identifiers)]</sup>
|
2039
|
+
|
2040
|
+
```Ruby
|
2041
|
+
# bad - identifier using non-ascii characters
|
2042
|
+
заплата = 1_000
|
2043
|
+
|
2044
|
+
# bad - identifier is a Bulgarian word, written with Latin letters (instead of Cyrillic)
|
2045
|
+
zaplata = 1_000
|
2046
|
+
|
2047
|
+
# good
|
2048
|
+
salary = 1_000
|
2049
|
+
```
|
2050
|
+
|
2051
|
+
* <a name="snake-case-symbols-methods-vars"></a>
|
2052
|
+
Use `snake_case` for symbols, methods and variables.
|
2053
|
+
<sup>[[link](#snake-case-symbols-methods-vars)]</sup>
|
2054
|
+
|
2055
|
+
```Ruby
|
2056
|
+
# bad
|
2057
|
+
:'some symbol'
|
2058
|
+
:SomeSymbol
|
2059
|
+
:someSymbol
|
2060
|
+
|
2061
|
+
someVar = 5
|
2062
|
+
var_10 = 10
|
2063
|
+
|
2064
|
+
def someMethod
|
2065
|
+
# some code
|
2066
|
+
end
|
2067
|
+
|
2068
|
+
def SomeMethod
|
2069
|
+
# some code
|
2070
|
+
end
|
2071
|
+
|
2072
|
+
# good
|
2073
|
+
:some_symbol
|
2074
|
+
|
2075
|
+
some_var = 5
|
2076
|
+
var10 = 10
|
2077
|
+
|
2078
|
+
def some_method
|
2079
|
+
# some code
|
2080
|
+
end
|
2081
|
+
```
|
2082
|
+
|
2083
|
+
* <a name="snake-case-symbols-methods-vars-with-numbers"></a>
|
2084
|
+
Do not separate numbers from letters on symbols, methods and variables.
|
2085
|
+
<sup>[[link](#snake-case-symbols-methods-vars-with-numbers)]</sup>
|
2086
|
+
|
2087
|
+
```Ruby
|
2088
|
+
# bad
|
2089
|
+
:some_sym_1
|
2090
|
+
|
2091
|
+
some_var_1 = 1
|
2092
|
+
|
2093
|
+
def some_method_1
|
2094
|
+
# some code
|
2095
|
+
end
|
2096
|
+
|
2097
|
+
# good
|
2098
|
+
:some_sym1
|
2099
|
+
|
2100
|
+
some_var1 = 1
|
2101
|
+
|
2102
|
+
def some_method1
|
2103
|
+
# some code
|
2104
|
+
end
|
2105
|
+
```
|
2106
|
+
|
2107
|
+
|
2108
|
+
* <a name="camelcase-classes"></a>
|
2109
|
+
Use `CamelCase` for classes and modules. (Keep acronyms like HTTP, RFC, XML
|
2110
|
+
uppercase.)
|
2111
|
+
<sup>[[link](#camelcase-classes)]</sup>
|
2112
|
+
|
2113
|
+
```Ruby
|
2114
|
+
# bad
|
2115
|
+
class Someclass
|
2116
|
+
# some code
|
2117
|
+
end
|
2118
|
+
|
2119
|
+
class Some_Class
|
2120
|
+
# some code
|
2121
|
+
end
|
2122
|
+
|
2123
|
+
class SomeXml
|
2124
|
+
# some code
|
2125
|
+
end
|
2126
|
+
|
2127
|
+
class XmlSomething
|
2128
|
+
# some code
|
2129
|
+
end
|
2130
|
+
|
2131
|
+
# good
|
2132
|
+
class SomeClass
|
2133
|
+
# some code
|
2134
|
+
end
|
2135
|
+
|
2136
|
+
class SomeXML
|
2137
|
+
# some code
|
2138
|
+
end
|
2139
|
+
|
2140
|
+
class XMLSomething
|
2141
|
+
# some code
|
2142
|
+
end
|
2143
|
+
```
|
2144
|
+
|
2145
|
+
* <a name="snake-case-files"></a>
|
2146
|
+
Use `snake_case` for naming files, e.g. `hello_world.rb`.
|
2147
|
+
<sup>[[link](#snake-case-files)]</sup>
|
2148
|
+
|
2149
|
+
* <a name="snake-case-dirs"></a>
|
2150
|
+
Use `snake_case` for naming directories, e.g.
|
2151
|
+
`lib/hello_world/hello_world.rb`.
|
2152
|
+
<sup>[[link](#snake-case-dirs)]</sup>
|
2153
|
+
|
2154
|
+
* <a name="one-class-per-file"></a>
|
2155
|
+
Aim to have just a single class/module per source file. Name the file name
|
2156
|
+
as the class/module, but replacing CamelCase with snake_case.
|
2157
|
+
<sup>[[link](#one-class-per-file)]</sup>
|
2158
|
+
|
2159
|
+
* <a name="screaming-snake-case"></a>
|
2160
|
+
Use `SCREAMING_SNAKE_CASE` for other constants.
|
2161
|
+
<sup>[[link](#screaming-snake-case)]</sup>
|
2162
|
+
|
2163
|
+
```Ruby
|
2164
|
+
# bad
|
2165
|
+
SomeConst = 5
|
2166
|
+
|
2167
|
+
# good
|
2168
|
+
SOME_CONST = 5
|
2169
|
+
```
|
2170
|
+
|
2171
|
+
* <a name="bool-methods-qmark"></a>
|
2172
|
+
The names of predicate methods (methods that return a boolean value) should
|
2173
|
+
end in a question mark. (i.e. `Array#empty?`). Methods that don't return a
|
2174
|
+
boolean, shouldn't end in a question mark.
|
2175
|
+
<sup>[[link](#bool-methods-qmark)]</sup>
|
2176
|
+
|
2177
|
+
* <a name="bool-methods-prefix"></a>
|
2178
|
+
Avoid prefixing predicate methods with the auxiliary verbs such as `is`,
|
2179
|
+
`does`, or `can`. These words are redundant and inconsistent with the style of
|
2180
|
+
boolean methods in the Ruby core library, such as `empty?` and `include?`.
|
2181
|
+
<sup>[[link](#bool-methods-prefix)]</sup>
|
2182
|
+
|
2183
|
+
```Ruby
|
2184
|
+
# bad
|
2185
|
+
class Person
|
2186
|
+
def is_tall?
|
2187
|
+
true
|
2188
|
+
end
|
2189
|
+
|
2190
|
+
def can_play_basketball?
|
2191
|
+
false
|
2192
|
+
end
|
2193
|
+
|
2194
|
+
def does_like_candy?
|
2195
|
+
true
|
2196
|
+
end
|
2197
|
+
end
|
2198
|
+
|
2199
|
+
# good
|
2200
|
+
class Person
|
2201
|
+
def tall?
|
2202
|
+
true
|
2203
|
+
end
|
2204
|
+
|
2205
|
+
def basketball_player?
|
2206
|
+
false
|
2207
|
+
end
|
2208
|
+
|
2209
|
+
def likes_candy?
|
2210
|
+
true
|
2211
|
+
end
|
2212
|
+
end
|
2213
|
+
```
|
2214
|
+
|
2215
|
+
* <a name="dangerous-method-bang"></a>
|
2216
|
+
The names of potentially *dangerous* methods (i.e. methods that modify
|
2217
|
+
`self` or the arguments, `exit!` (doesn't run the finalizers like `exit`
|
2218
|
+
does), etc.) should end with an exclamation mark if there exists a safe
|
2219
|
+
version of that *dangerous* method.
|
2220
|
+
<sup>[[link](#dangerous-method-bang)]</sup>
|
2221
|
+
|
2222
|
+
```Ruby
|
2223
|
+
# bad - there is no matching 'safe' method
|
2224
|
+
class Person
|
2225
|
+
def update!
|
2226
|
+
end
|
2227
|
+
end
|
2228
|
+
|
2229
|
+
# good
|
2230
|
+
class Person
|
2231
|
+
def update
|
2232
|
+
end
|
2233
|
+
end
|
2234
|
+
|
2235
|
+
# good
|
2236
|
+
class Person
|
2237
|
+
def update!
|
2238
|
+
end
|
2239
|
+
|
2240
|
+
def update
|
2241
|
+
end
|
2242
|
+
end
|
2243
|
+
```
|
2244
|
+
|
2245
|
+
* <a name="safe-because-unsafe"></a>
|
2246
|
+
Define the non-bang (safe) method in terms of the bang (dangerous) one if
|
2247
|
+
possible.
|
2248
|
+
<sup>[[link](#safe-because-unsafe)]</sup>
|
2249
|
+
|
2250
|
+
```Ruby
|
2251
|
+
class Array
|
2252
|
+
def flatten_once!
|
2253
|
+
res = []
|
2254
|
+
|
2255
|
+
each do |e|
|
2256
|
+
[*e].each { |f| res << f }
|
2257
|
+
end
|
2258
|
+
|
2259
|
+
replace(res)
|
2260
|
+
end
|
2261
|
+
|
2262
|
+
def flatten_once
|
2263
|
+
dup.flatten_once!
|
2264
|
+
end
|
2265
|
+
end
|
2266
|
+
```
|
2267
|
+
|
2268
|
+
* <a name="other-arg"></a>
|
2269
|
+
When defining binary operators, name the parameter `other`(`<<` and `[]` are
|
2270
|
+
exceptions to the rule, since their semantics are different).
|
2271
|
+
<sup>[[link](#other-arg)]</sup>
|
2272
|
+
|
2273
|
+
```Ruby
|
2274
|
+
def +(other)
|
2275
|
+
# body omitted
|
2276
|
+
end
|
2277
|
+
```
|
2278
|
+
|
2279
|
+
## Comments
|
2280
|
+
|
2281
|
+
> Good code is its own best documentation. As you're about to add a
|
2282
|
+
> comment, ask yourself, "How can I improve the code so that this
|
2283
|
+
> comment isn't needed?" Improve the code and then document it to make
|
2284
|
+
> it even clearer. <br>
|
2285
|
+
> -- Steve McConnell
|
2286
|
+
|
2287
|
+
* <a name="no-comments"></a>
|
2288
|
+
Write self-documenting code and ignore the rest of this section. Seriously!
|
2289
|
+
<sup>[[link](#no-comments)]</sup>
|
2290
|
+
|
2291
|
+
* <a name="english-comments"></a>
|
2292
|
+
Write comments in English.
|
2293
|
+
<sup>[[link](#english-comments)]</sup>
|
2294
|
+
|
2295
|
+
* <a name="hash-space"></a>
|
2296
|
+
Use one space between the leading `#` character of the comment and the text
|
2297
|
+
of the comment.
|
2298
|
+
<sup>[[link](#hash-space)]</sup>
|
2299
|
+
|
2300
|
+
* <a name="english-syntax"></a>
|
2301
|
+
Comments longer than a word are capitalized and use punctuation. Use [one
|
2302
|
+
space](https://en.wikipedia.org/wiki/Sentence_spacing) after periods.
|
2303
|
+
<sup>[[link](#english-syntax)]</sup>
|
2304
|
+
|
2305
|
+
* <a name="no-superfluous-comments"></a>
|
2306
|
+
Avoid superfluous comments.
|
2307
|
+
<sup>[[link](#no-superfluous-comments)]</sup>
|
2308
|
+
|
2309
|
+
```Ruby
|
2310
|
+
# bad
|
2311
|
+
counter += 1 # Increments counter by one.
|
2312
|
+
```
|
2313
|
+
|
2314
|
+
* <a name="comment-upkeep"></a>
|
2315
|
+
Keep existing comments up-to-date. An outdated comment is worse than no
|
2316
|
+
comment at all.
|
2317
|
+
<sup>[[link](#comment-upkeep)]</sup>
|
2318
|
+
|
2319
|
+
> Good code is like a good joke: it needs no explanation. <br>
|
2320
|
+
> — old programmers maxim, through [Russ Olsen](http://eloquentruby.com/blog/2011/03/07/good-code-and-good-jokes/)
|
2321
|
+
|
2322
|
+
* <a name="refactor-dont-comment"></a>
|
2323
|
+
Avoid writing comments to explain bad code. Refactor the code to make it
|
2324
|
+
self-explanatory. ("Do or do not—there is no try." Yoda)
|
2325
|
+
<sup>[[link](#refactor-dont-comment)]</sup>
|
2326
|
+
|
2327
|
+
### Comment Annotations
|
2328
|
+
|
2329
|
+
* <a name="annotate-above"></a>
|
2330
|
+
Annotations should usually be written on the line immediately above the
|
2331
|
+
relevant code.
|
2332
|
+
<sup>[[link](#annotate-above)]</sup>
|
2333
|
+
|
2334
|
+
* <a name="annotate-keywords"></a>
|
2335
|
+
The annotation keyword is followed by a colon and a space, then a note
|
2336
|
+
describing the problem.
|
2337
|
+
<sup>[[link](#annotate-keywords)]</sup>
|
2338
|
+
|
2339
|
+
* <a name="indent-annotations"></a>
|
2340
|
+
If multiple lines are required to describe the problem, subsequent lines
|
2341
|
+
should be indented three spaces after the `#` (one general plus two for
|
2342
|
+
indentation purpose).
|
2343
|
+
<sup>[[link](#indent-annotations)]</sup>
|
2344
|
+
|
2345
|
+
```Ruby
|
2346
|
+
def bar
|
2347
|
+
# FIXME: This has crashed occasionally since v3.2.1. It may
|
2348
|
+
# be related to the BarBazUtil upgrade.
|
2349
|
+
baz(:quux)
|
2350
|
+
end
|
2351
|
+
```
|
2352
|
+
|
2353
|
+
* <a name="rare-eol-annotations"></a>
|
2354
|
+
In cases where the problem is so obvious that any documentation would be
|
2355
|
+
redundant, annotations may be left at the end of the offending line with no
|
2356
|
+
note. This usage should be the exception and not the rule.
|
2357
|
+
<sup>[[link](#rare-eol-annotations)]</sup>
|
2358
|
+
|
2359
|
+
```Ruby
|
2360
|
+
def bar
|
2361
|
+
sleep 100 # OPTIMIZE
|
2362
|
+
end
|
2363
|
+
```
|
2364
|
+
|
2365
|
+
* <a name="todo"></a>
|
2366
|
+
Use `TODO` to note missing features or functionality that should be added at
|
2367
|
+
a later date.
|
2368
|
+
<sup>[[link](#todo)]</sup>
|
2369
|
+
|
2370
|
+
* <a name="fixme"></a>
|
2371
|
+
Use `FIXME` to note broken code that needs to be fixed.
|
2372
|
+
<sup>[[link](#fixme)]</sup>
|
2373
|
+
|
2374
|
+
* <a name="optimize"></a>
|
2375
|
+
Use `OPTIMIZE` to note slow or inefficient code that may cause performance
|
2376
|
+
problems.
|
2377
|
+
<sup>[[link](#optimize)]</sup>
|
2378
|
+
|
2379
|
+
* <a name="hack"></a>
|
2380
|
+
Use `HACK` to note code smells where questionable coding practices were used
|
2381
|
+
and should be refactored away.
|
2382
|
+
<sup>[[link](#hack)]</sup>
|
2383
|
+
|
2384
|
+
* <a name="review"></a>
|
2385
|
+
Use `REVIEW` to note anything that should be looked at to confirm it is
|
2386
|
+
working as intended. For example: `REVIEW: Are we sure this is how the client
|
2387
|
+
does X currently?`
|
2388
|
+
<sup>[[link](#review)]</sup>
|
2389
|
+
|
2390
|
+
* <a name="document-annotations"></a>
|
2391
|
+
Use other custom annotation keywords if it feels appropriate, but be sure to
|
2392
|
+
document them in your project's `README` or similar.
|
2393
|
+
<sup>[[link](#document-annotations)]</sup>
|
2394
|
+
|
2395
|
+
### Magic Comments
|
2396
|
+
|
2397
|
+
* <a name="magic-comments-first"></a>
|
2398
|
+
Place magic comments above all code and documentation. Magic comments should only go below shebangs if they are needed in your source file.
|
2399
|
+
<sup>[[link](#magic-comments-first)]</sup>
|
2400
|
+
|
2401
|
+
```Ruby
|
2402
|
+
# good
|
2403
|
+
# frozen_string_literal: true
|
2404
|
+
# Some documentation about Person
|
2405
|
+
class Person
|
2406
|
+
end
|
2407
|
+
|
2408
|
+
# bad
|
2409
|
+
# Some documentation about Person
|
2410
|
+
# frozen_string_literal: true
|
2411
|
+
class Person
|
2412
|
+
end
|
2413
|
+
```
|
2414
|
+
|
2415
|
+
```Ruby
|
2416
|
+
# good
|
2417
|
+
#!/usr/bin/env ruby
|
2418
|
+
# frozen_string_literal: true
|
2419
|
+
App.parse(ARGV)
|
2420
|
+
|
2421
|
+
# bad
|
2422
|
+
# frozen_string_literal: true
|
2423
|
+
#!/usr/bin/env ruby
|
2424
|
+
App.parse(ARGV)
|
2425
|
+
```
|
2426
|
+
|
2427
|
+
* <a name="one-magic-comment-per-line"></a>
|
2428
|
+
Use one magic comment per line if you need multiple.
|
2429
|
+
<sup>[[link](#one-magic-comment-per-line)]</sup>
|
2430
|
+
|
2431
|
+
```Ruby
|
2432
|
+
# good
|
2433
|
+
# frozen_string_literal: true
|
2434
|
+
# encoding: ascii-8bit
|
2435
|
+
|
2436
|
+
# bad
|
2437
|
+
# -*- frozen_string_literal: true; encoding: ascii-8bit -*-
|
2438
|
+
```
|
2439
|
+
|
2440
|
+
* <a name="separate-magic-comments-from-code"></a>
|
2441
|
+
Separate magic comments from code and documentation with a blank line.
|
2442
|
+
<sup>[[link](#separate-magic-comments-from-code)]</sup>
|
2443
|
+
|
2444
|
+
```Ruby
|
2445
|
+
# good
|
2446
|
+
# frozen_string_literal: true
|
2447
|
+
|
2448
|
+
# Some documentation for Person
|
2449
|
+
class Person
|
2450
|
+
# Some code
|
2451
|
+
end
|
2452
|
+
|
2453
|
+
# bad
|
2454
|
+
# frozen_string_literal: true
|
2455
|
+
# Some documentation for Person
|
2456
|
+
class Person
|
2457
|
+
# Some code
|
2458
|
+
end
|
2459
|
+
```
|
2460
|
+
|
2461
|
+
## Classes & Modules
|
2462
|
+
|
2463
|
+
* <a name="consistent-classes"></a>
|
2464
|
+
Use a consistent structure in your class definitions.
|
2465
|
+
<sup>[[link](#consistent-classes)]</sup>
|
2466
|
+
|
2467
|
+
```Ruby
|
2468
|
+
class Person
|
2469
|
+
# extend and include go first
|
2470
|
+
extend SomeModule
|
2471
|
+
include AnotherModule
|
2472
|
+
|
2473
|
+
# inner classes
|
2474
|
+
CustomError = Class.new(StandardError)
|
2475
|
+
|
2476
|
+
# constants are next
|
2477
|
+
SOME_CONSTANT = 20
|
2478
|
+
|
2479
|
+
# afterwards we have attribute macros
|
2480
|
+
attr_reader :name
|
2481
|
+
|
2482
|
+
# followed by other macros (if any)
|
2483
|
+
validates :name
|
2484
|
+
|
2485
|
+
# public class methods are next in line
|
2486
|
+
def self.some_method
|
2487
|
+
end
|
2488
|
+
|
2489
|
+
# initialization goes between class methods and other instance methods
|
2490
|
+
def initialize
|
2491
|
+
end
|
2492
|
+
|
2493
|
+
# followed by other public instance methods
|
2494
|
+
def some_method
|
2495
|
+
end
|
2496
|
+
|
2497
|
+
# protected and private methods are grouped near the end
|
2498
|
+
protected
|
2499
|
+
|
2500
|
+
def some_protected_method
|
2501
|
+
end
|
2502
|
+
|
2503
|
+
private
|
2504
|
+
|
2505
|
+
def some_private_method
|
2506
|
+
end
|
2507
|
+
end
|
2508
|
+
```
|
2509
|
+
|
2510
|
+
* <a name="mixin-grouping"></a>
|
2511
|
+
Split multiple mixins into separate statements.
|
2512
|
+
<sup>[[link](#mixin-grouping)]</sup>
|
2513
|
+
|
2514
|
+
```Ruby
|
2515
|
+
# bad
|
2516
|
+
class Person
|
2517
|
+
include Foo, Bar
|
2518
|
+
end
|
2519
|
+
|
2520
|
+
# good
|
2521
|
+
class Person
|
2522
|
+
# multiple mixins go in separate statements
|
2523
|
+
include Foo
|
2524
|
+
include Bar
|
2525
|
+
end
|
2526
|
+
```
|
2527
|
+
|
2528
|
+
* <a name="file-classes"></a>
|
2529
|
+
Don't nest multi-line classes within classes. Try to have such nested
|
2530
|
+
classes each in their own file in a folder named like the containing class.
|
2531
|
+
<sup>[[link](#file-classes)]</sup>
|
2532
|
+
|
2533
|
+
```Ruby
|
2534
|
+
# bad
|
2535
|
+
|
2536
|
+
# foo.rb
|
2537
|
+
class Foo
|
2538
|
+
class Bar
|
2539
|
+
# 30 methods inside
|
2540
|
+
end
|
2541
|
+
|
2542
|
+
class Car
|
2543
|
+
# 20 methods inside
|
2544
|
+
end
|
2545
|
+
|
2546
|
+
# 30 methods inside
|
2547
|
+
end
|
2548
|
+
|
2549
|
+
# good
|
2550
|
+
|
2551
|
+
# foo.rb
|
2552
|
+
class Foo
|
2553
|
+
# 30 methods inside
|
2554
|
+
end
|
2555
|
+
|
2556
|
+
# foo/bar.rb
|
2557
|
+
class Foo
|
2558
|
+
class Bar
|
2559
|
+
# 30 methods inside
|
2560
|
+
end
|
2561
|
+
end
|
2562
|
+
|
2563
|
+
# foo/car.rb
|
2564
|
+
class Foo
|
2565
|
+
class Car
|
2566
|
+
# 20 methods inside
|
2567
|
+
end
|
2568
|
+
end
|
2569
|
+
```
|
2570
|
+
|
2571
|
+
* <a name="modules-vs-classes"></a>
|
2572
|
+
Prefer modules to classes with only class methods. Classes should be used
|
2573
|
+
only when it makes sense to create instances out of them.
|
2574
|
+
<sup>[[link](#modules-vs-classes)]</sup>
|
2575
|
+
|
2576
|
+
```Ruby
|
2577
|
+
# bad
|
2578
|
+
class SomeClass
|
2579
|
+
def self.some_method
|
2580
|
+
# body omitted
|
2581
|
+
end
|
2582
|
+
|
2583
|
+
def self.some_other_method
|
2584
|
+
# body omitted
|
2585
|
+
end
|
2586
|
+
end
|
2587
|
+
|
2588
|
+
# good
|
2589
|
+
module SomeModule
|
2590
|
+
module_function
|
2591
|
+
|
2592
|
+
def some_method
|
2593
|
+
# body omitted
|
2594
|
+
end
|
2595
|
+
|
2596
|
+
def some_other_method
|
2597
|
+
# body omitted
|
2598
|
+
end
|
2599
|
+
end
|
2600
|
+
```
|
2601
|
+
|
2602
|
+
* <a name="module-function"></a>
|
2603
|
+
Favor the use of `module_function` over `extend self` when you want to turn
|
2604
|
+
a module's instance methods into class methods.
|
2605
|
+
<sup>[[link](#module-function)]</sup>
|
2606
|
+
|
2607
|
+
```Ruby
|
2608
|
+
# bad
|
2609
|
+
module Utilities
|
2610
|
+
extend self
|
2611
|
+
|
2612
|
+
def parse_something(string)
|
2613
|
+
# do stuff here
|
2614
|
+
end
|
2615
|
+
|
2616
|
+
def other_utility_method(number, string)
|
2617
|
+
# do some more stuff
|
2618
|
+
end
|
2619
|
+
end
|
2620
|
+
|
2621
|
+
# good
|
2622
|
+
module Utilities
|
2623
|
+
module_function
|
2624
|
+
|
2625
|
+
def parse_something(string)
|
2626
|
+
# do stuff here
|
2627
|
+
end
|
2628
|
+
|
2629
|
+
def other_utility_method(number, string)
|
2630
|
+
# do some more stuff
|
2631
|
+
end
|
2632
|
+
end
|
2633
|
+
```
|
2634
|
+
|
2635
|
+
* <a name="liskov"></a>
|
2636
|
+
When designing class hierarchies make sure that they conform to the [Liskov
|
2637
|
+
Substitution
|
2638
|
+
Principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle).
|
2639
|
+
<sup>[[link](#liskov)]</sup>
|
2640
|
+
|
2641
|
+
* <a name="solid-design"></a>
|
2642
|
+
Try to make your classes as
|
2643
|
+
[SOLID](https://en.wikipedia.org/wiki/SOLID_\(object-oriented_design\)) as
|
2644
|
+
possible.
|
2645
|
+
<sup>[[link](#solid-design)]</sup>
|
2646
|
+
|
2647
|
+
* <a name="define-to-s"></a>
|
2648
|
+
Always supply a proper `to_s` method for classes that represent domain
|
2649
|
+
objects.
|
2650
|
+
<sup>[[link](#define-to-s)]</sup>
|
2651
|
+
|
2652
|
+
```Ruby
|
2653
|
+
class Person
|
2654
|
+
attr_reader :first_name, :last_name
|
2655
|
+
|
2656
|
+
def initialize(first_name, last_name)
|
2657
|
+
@first_name = first_name
|
2658
|
+
@last_name = last_name
|
2659
|
+
end
|
2660
|
+
|
2661
|
+
def to_s
|
2662
|
+
"#{@first_name} #{@last_name}"
|
2663
|
+
end
|
2664
|
+
end
|
2665
|
+
```
|
2666
|
+
|
2667
|
+
* <a name="attr_family"></a>
|
2668
|
+
Use the `attr` family of functions to define trivial accessors or mutators.
|
2669
|
+
<sup>[[link](#attr_family)]</sup>
|
2670
|
+
|
2671
|
+
```Ruby
|
2672
|
+
# bad
|
2673
|
+
class Person
|
2674
|
+
def initialize(first_name, last_name)
|
2675
|
+
@first_name = first_name
|
2676
|
+
@last_name = last_name
|
2677
|
+
end
|
2678
|
+
|
2679
|
+
def first_name
|
2680
|
+
@first_name
|
2681
|
+
end
|
2682
|
+
|
2683
|
+
def last_name
|
2684
|
+
@last_name
|
2685
|
+
end
|
2686
|
+
end
|
2687
|
+
|
2688
|
+
# good
|
2689
|
+
class Person
|
2690
|
+
attr_reader :first_name, :last_name
|
2691
|
+
|
2692
|
+
def initialize(first_name, last_name)
|
2693
|
+
@first_name = first_name
|
2694
|
+
@last_name = last_name
|
2695
|
+
end
|
2696
|
+
end
|
2697
|
+
```
|
2698
|
+
|
2699
|
+
* <a name="accessor_mutator_method_names"></a>
|
2700
|
+
For accessors and mutators, avoid prefixing method names with
|
2701
|
+
`get_` and `set_`.
|
2702
|
+
It is a Ruby convention to use attribute names for accessors (readers) and
|
2703
|
+
`attr_name=` for mutators (writers).
|
2704
|
+
<sup>[[link](#accessor_mutator_method_names)]</sup>
|
2705
|
+
|
2706
|
+
```Ruby
|
2707
|
+
# bad
|
2708
|
+
class Person
|
2709
|
+
def get_name
|
2710
|
+
"#{@first_name} #{@last_name}"
|
2711
|
+
end
|
2712
|
+
|
2713
|
+
def set_name(name)
|
2714
|
+
@first_name, @last_name = name.split(' ')
|
2715
|
+
end
|
2716
|
+
end
|
2717
|
+
|
2718
|
+
# good
|
2719
|
+
class Person
|
2720
|
+
def name
|
2721
|
+
"#{@first_name} #{@last_name}"
|
2722
|
+
end
|
2723
|
+
|
2724
|
+
def name=(name)
|
2725
|
+
@first_name, @last_name = name.split(' ')
|
2726
|
+
end
|
2727
|
+
end
|
2728
|
+
```
|
2729
|
+
|
2730
|
+
* <a name="attr"></a>
|
2731
|
+
Avoid the use of `attr`. Use `attr_reader` and `attr_accessor` instead.
|
2732
|
+
<sup>[[link](#attr)]</sup>
|
2733
|
+
|
2734
|
+
```Ruby
|
2735
|
+
# bad - creates a single attribute accessor (deprecated in Ruby 1.9)
|
2736
|
+
attr :something, true
|
2737
|
+
attr :one, :two, :three # behaves as attr_reader
|
2738
|
+
|
2739
|
+
# good
|
2740
|
+
attr_accessor :something
|
2741
|
+
attr_reader :one, :two, :three
|
2742
|
+
```
|
2743
|
+
|
2744
|
+
* <a name="struct-new"></a>
|
2745
|
+
Consider using `Struct.new`, which defines the trivial accessors,
|
2746
|
+
constructor and comparison operators for you.
|
2747
|
+
<sup>[[link](#struct-new)]</sup>
|
2748
|
+
|
2749
|
+
```Ruby
|
2750
|
+
# good
|
2751
|
+
class Person
|
2752
|
+
attr_accessor :first_name, :last_name
|
2753
|
+
|
2754
|
+
def initialize(first_name, last_name)
|
2755
|
+
@first_name = first_name
|
2756
|
+
@last_name = last_name
|
2757
|
+
end
|
2758
|
+
end
|
2759
|
+
|
2760
|
+
# better
|
2761
|
+
Person = Struct.new(:first_name, :last_name) do
|
2762
|
+
end
|
2763
|
+
```
|
2764
|
+
|
2765
|
+
* <a name="no-extend-struct-new"></a>
|
2766
|
+
Don't extend an instance initialized by `Struct.new`. Extending it introduces
|
2767
|
+
a superfluous class level and may also introduce weird errors if the file is
|
2768
|
+
required multiple times.
|
2769
|
+
<sup>[[link](#no-extend-struct-new)]</sup>
|
2770
|
+
|
2771
|
+
```Ruby
|
2772
|
+
# bad
|
2773
|
+
class Person < Struct.new(:first_name, :last_name)
|
2774
|
+
end
|
2775
|
+
|
2776
|
+
# good
|
2777
|
+
Person = Struct.new(:first_name, :last_name)
|
2778
|
+
```
|
2779
|
+
|
2780
|
+
* <a name="factory-methods"></a>
|
2781
|
+
Consider adding factory methods to provide additional sensible ways to
|
2782
|
+
create instances of a particular class.
|
2783
|
+
<sup>[[link](#factory-methods)]</sup>
|
2784
|
+
|
2785
|
+
```Ruby
|
2786
|
+
class Person
|
2787
|
+
def self.create(options_hash)
|
2788
|
+
# body omitted
|
2789
|
+
end
|
2790
|
+
end
|
2791
|
+
```
|
2792
|
+
|
2793
|
+
* <a name="duck-typing"></a>
|
2794
|
+
Prefer [duck-typing](https://en.wikipedia.org/wiki/Duck_typing) over
|
2795
|
+
inheritance.
|
2796
|
+
<sup>[[link](#duck-typing)]</sup>
|
2797
|
+
|
2798
|
+
```Ruby
|
2799
|
+
# bad
|
2800
|
+
class Animal
|
2801
|
+
# abstract method
|
2802
|
+
def speak
|
2803
|
+
end
|
2804
|
+
end
|
2805
|
+
|
2806
|
+
# extend superclass
|
2807
|
+
class Duck < Animal
|
2808
|
+
def speak
|
2809
|
+
puts 'Quack! Quack'
|
2810
|
+
end
|
2811
|
+
end
|
2812
|
+
|
2813
|
+
# extend superclass
|
2814
|
+
class Dog < Animal
|
2815
|
+
def speak
|
2816
|
+
puts 'Bau! Bau!'
|
2817
|
+
end
|
2818
|
+
end
|
2819
|
+
|
2820
|
+
# good
|
2821
|
+
class Duck
|
2822
|
+
def speak
|
2823
|
+
puts 'Quack! Quack'
|
2824
|
+
end
|
2825
|
+
end
|
2826
|
+
|
2827
|
+
class Dog
|
2828
|
+
def speak
|
2829
|
+
puts 'Bau! Bau!'
|
2830
|
+
end
|
2831
|
+
end
|
2832
|
+
```
|
2833
|
+
|
2834
|
+
* <a name="no-class-vars"></a>
|
2835
|
+
Avoid the usage of class (`@@`) variables due to their "nasty" behavior in
|
2836
|
+
inheritance.
|
2837
|
+
<sup>[[link](#no-class-vars)]</sup>
|
2838
|
+
|
2839
|
+
```Ruby
|
2840
|
+
class Parent
|
2841
|
+
@@class_var = 'parent'
|
2842
|
+
|
2843
|
+
def self.print_class_var
|
2844
|
+
puts @@class_var
|
2845
|
+
end
|
2846
|
+
end
|
2847
|
+
|
2848
|
+
class Child < Parent
|
2849
|
+
@@class_var = 'child'
|
2850
|
+
end
|
2851
|
+
|
2852
|
+
Parent.print_class_var # => will print 'child'
|
2853
|
+
```
|
2854
|
+
|
2855
|
+
As you can see all the classes in a class hierarchy actually share one
|
2856
|
+
class variable. Class instance variables should usually be preferred
|
2857
|
+
over class variables.
|
2858
|
+
|
2859
|
+
* <a name="visibility"></a>
|
2860
|
+
Assign proper visibility levels to methods (`private`, `protected`) in
|
2861
|
+
accordance with their intended usage. Don't go off leaving everything `public`
|
2862
|
+
(which is the default). After all we're coding in *Ruby* now, not in *Python*.
|
2863
|
+
<sup>[[link](#visibility)]</sup>
|
2864
|
+
|
2865
|
+
* <a name="indent-public-private-protected"></a>
|
2866
|
+
Indent the `public`, `protected`, and `private` methods as much as the method
|
2867
|
+
definitions they apply to. Leave one blank line above the visibility modifier
|
2868
|
+
and one blank line below in order to emphasize that it applies to all methods
|
2869
|
+
below it.
|
2870
|
+
<sup>[[link](#indent-public-private-protected)]</sup>
|
2871
|
+
|
2872
|
+
```Ruby
|
2873
|
+
class SomeClass
|
2874
|
+
def public_method
|
2875
|
+
# some code
|
2876
|
+
end
|
2877
|
+
|
2878
|
+
private
|
2879
|
+
|
2880
|
+
def private_method
|
2881
|
+
# some code
|
2882
|
+
end
|
2883
|
+
|
2884
|
+
def another_private_method
|
2885
|
+
# some code
|
2886
|
+
end
|
2887
|
+
end
|
2888
|
+
```
|
2889
|
+
|
2890
|
+
* <a name="def-self-class-methods"></a>
|
2891
|
+
Use `def self.method` to define class methods. This makes the code
|
2892
|
+
easier to refactor since the class name is not repeated.
|
2893
|
+
<sup>[[link](#def-self-class-methods)]</sup>
|
2894
|
+
|
2895
|
+
```Ruby
|
2896
|
+
class TestClass
|
2897
|
+
# bad
|
2898
|
+
def TestClass.some_method
|
2899
|
+
# body omitted
|
2900
|
+
end
|
2901
|
+
|
2902
|
+
# good
|
2903
|
+
def self.some_other_method
|
2904
|
+
# body omitted
|
2905
|
+
end
|
2906
|
+
|
2907
|
+
# Also possible and convenient when you
|
2908
|
+
# have to define many class methods.
|
2909
|
+
class << self
|
2910
|
+
def first_method
|
2911
|
+
# body omitted
|
2912
|
+
end
|
2913
|
+
|
2914
|
+
def second_method_etc
|
2915
|
+
# body omitted
|
2916
|
+
end
|
2917
|
+
end
|
2918
|
+
end
|
2919
|
+
```
|
2920
|
+
|
2921
|
+
* <a name="alias-method-lexically"></a>
|
2922
|
+
Prefer `alias` when aliasing methods in lexical class scope as the
|
2923
|
+
resolution of `self` in this context is also lexical, and it communicates
|
2924
|
+
clearly to the user that the indirection of your alias will not be altered
|
2925
|
+
at runtime or by any subclass unless made explicit.
|
2926
|
+
<sup>[[link](#alias-method-lexically)]</sup>
|
2927
|
+
|
2928
|
+
```Ruby
|
2929
|
+
class Westerner
|
2930
|
+
def first_name
|
2931
|
+
@names.first
|
2932
|
+
end
|
2933
|
+
|
2934
|
+
alias given_name first_name
|
2935
|
+
end
|
2936
|
+
```
|
2937
|
+
|
2938
|
+
Since `alias`, like `def`, is a keyword, prefer bareword arguments over
|
2939
|
+
symbols or strings. In other words, do `alias foo bar`, not
|
2940
|
+
`alias :foo :bar`.
|
2941
|
+
|
2942
|
+
Also be aware of how Ruby handles aliases and inheritance: an alias
|
2943
|
+
references the method that was resolved at the time the alias was defined;
|
2944
|
+
it is not dispatched dynamically.
|
2945
|
+
|
2946
|
+
```Ruby
|
2947
|
+
class Fugitive < Westerner
|
2948
|
+
def first_name
|
2949
|
+
'Nobody'
|
2950
|
+
end
|
2951
|
+
end
|
2952
|
+
```
|
2953
|
+
|
2954
|
+
In this example, `Fugitive#given_name` would still call the original
|
2955
|
+
`Westerner#first_name` method, not `Fugitive#first_name`. To override the
|
2956
|
+
behavior of `Fugitive#given_name` as well, you'd have to redefine it in the
|
2957
|
+
derived class.
|
2958
|
+
|
2959
|
+
```Ruby
|
2960
|
+
class Fugitive < Westerner
|
2961
|
+
def first_name
|
2962
|
+
'Nobody'
|
2963
|
+
end
|
2964
|
+
|
2965
|
+
alias given_name first_name
|
2966
|
+
end
|
2967
|
+
```
|
2968
|
+
|
2969
|
+
* <a name="alias-method"></a>
|
2970
|
+
Always use `alias_method` when aliasing methods of modules, classes, or
|
2971
|
+
singleton classes at runtime, as the lexical scope of `alias` leads to
|
2972
|
+
unpredictability in these cases.
|
2973
|
+
<sup>[[link](#alias-method)]</sup>
|
2974
|
+
|
2975
|
+
```Ruby
|
2976
|
+
module Mononymous
|
2977
|
+
def self.included(other)
|
2978
|
+
other.class_eval { alias_method :full_name, :given_name }
|
2979
|
+
end
|
2980
|
+
end
|
2981
|
+
|
2982
|
+
class Sting < Westerner
|
2983
|
+
include Mononymous
|
2984
|
+
end
|
2985
|
+
```
|
2986
|
+
|
2987
|
+
* <a name="class-and-self"></a>
|
2988
|
+
When class (or module) methods call other such methods, omit the use of a
|
2989
|
+
leading `self` or own name followed by a `.` when calling other such methods.
|
2990
|
+
This is often seen in "service classes" or other similar concepts where a
|
2991
|
+
class is treated as though it were a function. This convention tends to reduce
|
2992
|
+
repetitive boilerplate in such classes.
|
2993
|
+
<sup>[[link](#class-and-self)]</sup>
|
2994
|
+
|
2995
|
+
```Ruby
|
2996
|
+
class TestClass
|
2997
|
+
# bad -- more work when class renamed/method moved
|
2998
|
+
def self.call(param1, param2)
|
2999
|
+
TestClass.new(param1).call(param2)
|
3000
|
+
end
|
3001
|
+
|
3002
|
+
# bad -- more verbose than necessary
|
3003
|
+
def self.call(param1, param2)
|
3004
|
+
self.new(param1).call(param2)
|
3005
|
+
end
|
3006
|
+
|
3007
|
+
# good
|
3008
|
+
def self.call(param1, param2)
|
3009
|
+
new(param1).call(param2)
|
3010
|
+
end
|
3011
|
+
|
3012
|
+
# ...other methods...
|
3013
|
+
end
|
3014
|
+
```
|
3015
|
+
|
3016
|
+
## Exceptions
|
3017
|
+
|
3018
|
+
* <a name="prefer-raise-over-fail"></a>
|
3019
|
+
Prefer `raise` over `fail` for exceptions.
|
3020
|
+
<sup>[[link](#prefer-raise-over-fail)]</sup>
|
3021
|
+
|
3022
|
+
```Ruby
|
3023
|
+
# bad
|
3024
|
+
fail SomeException, 'message'
|
3025
|
+
|
3026
|
+
# good
|
3027
|
+
raise SomeException, 'message'
|
3028
|
+
```
|
3029
|
+
|
3030
|
+
* <a name="no-explicit-runtimeerror"></a>
|
3031
|
+
Don't specify `RuntimeError` explicitly in the two argument version of
|
3032
|
+
`raise`.
|
3033
|
+
<sup>[[link](#no-explicit-runtimeerror)]</sup>
|
3034
|
+
|
3035
|
+
```Ruby
|
3036
|
+
# bad
|
3037
|
+
raise RuntimeError, 'message'
|
3038
|
+
|
3039
|
+
# good - signals a RuntimeError by default
|
3040
|
+
raise 'message'
|
3041
|
+
```
|
3042
|
+
|
3043
|
+
* <a name="exception-class-messages"></a>
|
3044
|
+
Prefer supplying an exception class and a message as two separate arguments
|
3045
|
+
to `raise`, instead of an exception instance.
|
3046
|
+
<sup>[[link](#exception-class-messages)]</sup>
|
3047
|
+
|
3048
|
+
```Ruby
|
3049
|
+
# bad
|
3050
|
+
raise SomeException.new('message')
|
3051
|
+
# Note that there is no way to do `raise SomeException.new('message'), backtrace`.
|
3052
|
+
|
3053
|
+
# good
|
3054
|
+
raise SomeException, 'message'
|
3055
|
+
# Consistent with `raise SomeException, 'message', backtrace`.
|
3056
|
+
```
|
3057
|
+
|
3058
|
+
* <a name="no-return-ensure"></a>
|
3059
|
+
Do not return from an `ensure` block. If you explicitly return from a method
|
3060
|
+
inside an `ensure` block, the return will take precedence over any exception
|
3061
|
+
being raised, and the method will return as if no exception had been raised at
|
3062
|
+
all. In effect, the exception will be silently thrown away.
|
3063
|
+
<sup>[[link](#no-return-ensure)]</sup>
|
3064
|
+
|
3065
|
+
```Ruby
|
3066
|
+
# bad
|
3067
|
+
def foo
|
3068
|
+
raise
|
3069
|
+
ensure
|
3070
|
+
return 'very bad idea'
|
3071
|
+
end
|
3072
|
+
```
|
3073
|
+
|
3074
|
+
* <a name="begin-implicit"></a>
|
3075
|
+
Use *implicit begin blocks* where possible.
|
3076
|
+
<sup>[[link](#begin-implicit)]</sup>
|
3077
|
+
|
3078
|
+
```Ruby
|
3079
|
+
# bad
|
3080
|
+
def foo
|
3081
|
+
begin
|
3082
|
+
# main logic goes here
|
3083
|
+
rescue
|
3084
|
+
# failure handling goes here
|
3085
|
+
end
|
3086
|
+
end
|
3087
|
+
|
3088
|
+
# good
|
3089
|
+
def foo
|
3090
|
+
# main logic goes here
|
3091
|
+
rescue
|
3092
|
+
# failure handling goes here
|
3093
|
+
end
|
3094
|
+
```
|
3095
|
+
|
3096
|
+
* <a name="contingency-methods"></a>
|
3097
|
+
Mitigate the proliferation of `begin` blocks by using *contingency methods*
|
3098
|
+
(a term coined by Avdi Grimm).
|
3099
|
+
<sup>[[link](#contingency-methods)]</sup>
|
3100
|
+
|
3101
|
+
```Ruby
|
3102
|
+
# bad
|
3103
|
+
begin
|
3104
|
+
something_that_might_fail
|
3105
|
+
rescue IOError
|
3106
|
+
# handle IOError
|
3107
|
+
end
|
3108
|
+
|
3109
|
+
begin
|
3110
|
+
something_else_that_might_fail
|
3111
|
+
rescue IOError
|
3112
|
+
# handle IOError
|
3113
|
+
end
|
3114
|
+
|
3115
|
+
# good
|
3116
|
+
def with_io_error_handling
|
3117
|
+
yield
|
3118
|
+
rescue IOError
|
3119
|
+
# handle IOError
|
3120
|
+
end
|
3121
|
+
|
3122
|
+
with_io_error_handling { something_that_might_fail }
|
3123
|
+
|
3124
|
+
with_io_error_handling { something_else_that_might_fail }
|
3125
|
+
```
|
3126
|
+
|
3127
|
+
* <a name="dont-hide-exceptions"></a>
|
3128
|
+
Don't suppress exceptions.
|
3129
|
+
<sup>[[link](#dont-hide-exceptions)]</sup>
|
3130
|
+
|
3131
|
+
```Ruby
|
3132
|
+
# bad
|
3133
|
+
begin
|
3134
|
+
# an exception occurs here
|
3135
|
+
rescue SomeError
|
3136
|
+
# the rescue clause does absolutely nothing
|
3137
|
+
end
|
3138
|
+
|
3139
|
+
# bad
|
3140
|
+
do_something rescue nil
|
3141
|
+
```
|
3142
|
+
|
3143
|
+
* <a name="no-rescue-modifiers"></a>
|
3144
|
+
Avoid using `rescue` in its modifier form.
|
3145
|
+
<sup>[[link](#no-rescue-modifiers)]</sup>
|
3146
|
+
|
3147
|
+
```Ruby
|
3148
|
+
# bad - this catches exceptions of StandardError class and its descendant classes
|
3149
|
+
read_file rescue handle_error($!)
|
3150
|
+
|
3151
|
+
# good - this catches only the exceptions of Errno::ENOENT class and its descendant classes
|
3152
|
+
def foo
|
3153
|
+
read_file
|
3154
|
+
rescue Errno::ENOENT => ex
|
3155
|
+
handle_error(ex)
|
3156
|
+
end
|
3157
|
+
```
|
3158
|
+
|
3159
|
+
* <a name="no-exceptional-flows"></a>
|
3160
|
+
Don't use exceptions for flow of control.
|
3161
|
+
<sup>[[link](#no-exceptional-flows)]</sup>
|
3162
|
+
|
3163
|
+
```Ruby
|
3164
|
+
# bad
|
3165
|
+
begin
|
3166
|
+
n / d
|
3167
|
+
rescue ZeroDivisionError
|
3168
|
+
puts 'Cannot divide by 0!'
|
3169
|
+
end
|
3170
|
+
|
3171
|
+
# good
|
3172
|
+
if d.zero?
|
3173
|
+
puts 'Cannot divide by 0!'
|
3174
|
+
else
|
3175
|
+
n / d
|
3176
|
+
end
|
3177
|
+
```
|
3178
|
+
|
3179
|
+
* <a name="no-blind-rescues"></a>
|
3180
|
+
Avoid rescuing the `Exception` class. This will trap signals and calls to
|
3181
|
+
`exit`, requiring you to `kill -9` the process.
|
3182
|
+
<sup>[[link](#no-blind-rescues)]</sup>
|
3183
|
+
|
3184
|
+
```Ruby
|
3185
|
+
# bad
|
3186
|
+
begin
|
3187
|
+
# calls to exit and kill signals will be caught (except kill -9)
|
3188
|
+
exit
|
3189
|
+
rescue Exception
|
3190
|
+
puts "you didn't really want to exit, right?"
|
3191
|
+
# exception handling
|
3192
|
+
end
|
3193
|
+
|
3194
|
+
# good
|
3195
|
+
begin
|
3196
|
+
# a blind rescue rescues from StandardError, not Exception as many
|
3197
|
+
# programmers assume.
|
3198
|
+
rescue => e
|
3199
|
+
# exception handling
|
3200
|
+
end
|
3201
|
+
|
3202
|
+
# also good
|
3203
|
+
begin
|
3204
|
+
# an exception occurs here
|
3205
|
+
rescue StandardError => e
|
3206
|
+
# exception handling
|
3207
|
+
end
|
3208
|
+
```
|
3209
|
+
|
3210
|
+
* <a name="exception-ordering"></a>
|
3211
|
+
Put more specific exceptions higher up the rescue chain, otherwise they'll
|
3212
|
+
never be rescued from.
|
3213
|
+
<sup>[[link](#exception-ordering)]</sup>
|
3214
|
+
|
3215
|
+
```Ruby
|
3216
|
+
# bad
|
3217
|
+
begin
|
3218
|
+
# some code
|
3219
|
+
rescue StandardError => e
|
3220
|
+
# some handling
|
3221
|
+
rescue IOError => e
|
3222
|
+
# some handling that will never be executed
|
3223
|
+
end
|
3224
|
+
|
3225
|
+
# good
|
3226
|
+
begin
|
3227
|
+
# some code
|
3228
|
+
rescue IOError => e
|
3229
|
+
# some handling
|
3230
|
+
rescue StandardError => e
|
3231
|
+
# some handling
|
3232
|
+
end
|
3233
|
+
```
|
3234
|
+
|
3235
|
+
* <a name="release-resources"></a>
|
3236
|
+
Release external resources obtained by your program in an `ensure` block.
|
3237
|
+
<sup>[[link](#release-resources)]</sup>
|
3238
|
+
|
3239
|
+
```Ruby
|
3240
|
+
f = File.open('testfile')
|
3241
|
+
begin
|
3242
|
+
# .. process
|
3243
|
+
rescue
|
3244
|
+
# .. handle error
|
3245
|
+
ensure
|
3246
|
+
f.close if f
|
3247
|
+
end
|
3248
|
+
```
|
3249
|
+
|
3250
|
+
* <a name="auto-release-resources"></a>
|
3251
|
+
Use versions of resource obtaining methods that do automatic
|
3252
|
+
resource cleanup when possible.
|
3253
|
+
<sup>[[link](#auto-release-resources)]</sup>
|
3254
|
+
|
3255
|
+
```Ruby
|
3256
|
+
# bad - you need to close the file descriptor explicitly
|
3257
|
+
f = File.open('testfile')
|
3258
|
+
# some action on the file
|
3259
|
+
f.close
|
3260
|
+
|
3261
|
+
# good - the file descriptor is closed automatically
|
3262
|
+
File.open('testfile') do |f|
|
3263
|
+
# some action on the file
|
3264
|
+
end
|
3265
|
+
```
|
3266
|
+
|
3267
|
+
* <a name="standard-exceptions"></a>
|
3268
|
+
Favor the use of exceptions from the standard library over introducing new
|
3269
|
+
exception classes.
|
3270
|
+
<sup>[[link](#standard-exceptions)]</sup>
|
3271
|
+
|
3272
|
+
## Collections
|
3273
|
+
|
3274
|
+
* <a name="literal-array-hash"></a>
|
3275
|
+
Prefer literal array and hash creation notation (unless you need to pass
|
3276
|
+
parameters to their constructors, that is).
|
3277
|
+
<sup>[[link](#literal-array-hash)]</sup>
|
3278
|
+
|
3279
|
+
```Ruby
|
3280
|
+
# bad
|
3281
|
+
arr = Array.new
|
3282
|
+
hash = Hash.new
|
3283
|
+
|
3284
|
+
# good
|
3285
|
+
arr = []
|
3286
|
+
hash = {}
|
3287
|
+
```
|
3288
|
+
|
3289
|
+
* <a name="percent-w"></a>
|
3290
|
+
Prefer `%w` to the literal array syntax when you need an array of words
|
3291
|
+
(non-empty strings without spaces and special characters in them). Apply this
|
3292
|
+
rule only to arrays with two or more elements.
|
3293
|
+
<sup>[[link](#percent-w)]</sup>
|
3294
|
+
|
3295
|
+
```Ruby
|
3296
|
+
# bad
|
3297
|
+
STATES = ['draft', 'open', 'closed']
|
3298
|
+
|
3299
|
+
# good
|
3300
|
+
STATES = %w[draft open closed]
|
3301
|
+
```
|
3302
|
+
|
3303
|
+
* <a name="percent-i"></a>
|
3304
|
+
Prefer `%i` to the literal array syntax when you need an array of symbols
|
3305
|
+
(and you don't need to maintain Ruby 1.9 compatibility). Apply this rule only
|
3306
|
+
to arrays with two or more elements.
|
3307
|
+
<sup>[[link](#percent-i)]</sup>
|
3308
|
+
|
3309
|
+
```Ruby
|
3310
|
+
# bad
|
3311
|
+
STATES = [:draft, :open, :closed]
|
3312
|
+
|
3313
|
+
# good
|
3314
|
+
STATES = %i[draft open closed]
|
3315
|
+
```
|
3316
|
+
|
3317
|
+
* <a name="no-trailing-array-commas"></a>
|
3318
|
+
Avoid comma after the last item of an `Array` or `Hash` literal, especially
|
3319
|
+
when the items are not on separate lines.
|
3320
|
+
<sup>[[link](#no-trailing-array-commas)]</sup>
|
3321
|
+
|
3322
|
+
```Ruby
|
3323
|
+
# bad - easier to move/add/remove items, but still not preferred
|
3324
|
+
VALUES = [
|
3325
|
+
1001,
|
3326
|
+
2020,
|
3327
|
+
3333,
|
3328
|
+
]
|
3329
|
+
|
3330
|
+
# bad
|
3331
|
+
VALUES = [1001, 2020, 3333, ]
|
3332
|
+
|
3333
|
+
# good
|
3334
|
+
VALUES = [1001, 2020, 3333]
|
3335
|
+
```
|
3336
|
+
|
3337
|
+
* <a name="no-gappy-arrays"></a>
|
3338
|
+
Avoid the creation of huge gaps in arrays.
|
3339
|
+
<sup>[[link](#no-gappy-arrays)]</sup>
|
3340
|
+
|
3341
|
+
```Ruby
|
3342
|
+
arr = []
|
3343
|
+
arr[100] = 1 # now you have an array with lots of nils
|
3344
|
+
```
|
3345
|
+
|
3346
|
+
* <a name="first-and-last"></a>
|
3347
|
+
When accessing the first or last element from an array, prefer `first` or
|
3348
|
+
`last` over `[0]` or `[-1]`.
|
3349
|
+
<sup>[[link](#first-and-last)]</sup>
|
3350
|
+
|
3351
|
+
* <a name="set-vs-array"></a>
|
3352
|
+
Use `Set` instead of `Array` when dealing with unique elements. `Set`
|
3353
|
+
implements a collection of unordered values with no duplicates. This is a
|
3354
|
+
hybrid of `Array`'s intuitive inter-operation facilities and `Hash`'s fast
|
3355
|
+
lookup.
|
3356
|
+
<sup>[[link](#set-vs-array)]</sup>
|
3357
|
+
|
3358
|
+
* <a name="symbols-as-keys"></a>
|
3359
|
+
Prefer symbols instead of strings as hash keys.
|
3360
|
+
<sup>[[link](#symbols-as-keys)]</sup>
|
3361
|
+
|
3362
|
+
```Ruby
|
3363
|
+
# bad
|
3364
|
+
hash = { 'one' => 1, 'two' => 2, 'three' => 3 }
|
3365
|
+
|
3366
|
+
# good
|
3367
|
+
hash = { one: 1, two: 2, three: 3 }
|
3368
|
+
```
|
3369
|
+
|
3370
|
+
* <a name="no-mutable-keys"></a>
|
3371
|
+
Avoid the use of mutable objects as hash keys.
|
3372
|
+
<sup>[[link](#no-mutable-keys)]</sup>
|
3373
|
+
|
3374
|
+
* <a name="hash-literals"></a>
|
3375
|
+
Use the Ruby 1.9 hash literal syntax when your hash keys are symbols.
|
3376
|
+
<sup>[[link](#hash-literals)]</sup>
|
3377
|
+
|
3378
|
+
```Ruby
|
3379
|
+
# bad
|
3380
|
+
hash = { :one => 1, :two => 2, :three => 3 }
|
3381
|
+
|
3382
|
+
# good
|
3383
|
+
hash = { one: 1, two: 2, three: 3 }
|
3384
|
+
```
|
3385
|
+
|
3386
|
+
* <a name="no-mixed-hash-syntaces"></a>
|
3387
|
+
Don't mix the Ruby 1.9 hash syntax with hash rockets in the same hash
|
3388
|
+
literal. When you've got keys that are not symbols stick to the hash rockets
|
3389
|
+
syntax.
|
3390
|
+
<sup>[[link](#no-mixed-hash-syntaces)]</sup>
|
3391
|
+
|
3392
|
+
```Ruby
|
3393
|
+
# bad
|
3394
|
+
{ a: 1, 'b' => 2 }
|
3395
|
+
|
3396
|
+
# good
|
3397
|
+
{ :a => 1, 'b' => 2 }
|
3398
|
+
```
|
3399
|
+
|
3400
|
+
* <a name="hash-key"></a>
|
3401
|
+
Use `Hash#key?` instead of `Hash#has_key?` and `Hash#value?` instead of
|
3402
|
+
`Hash#has_value?`.
|
3403
|
+
<sup>[[link](#hash-key)]</sup>
|
3404
|
+
|
3405
|
+
```Ruby
|
3406
|
+
# bad
|
3407
|
+
hash.has_key?(:test)
|
3408
|
+
hash.has_value?(value)
|
3409
|
+
|
3410
|
+
# good
|
3411
|
+
hash.key?(:test)
|
3412
|
+
hash.value?(value)
|
3413
|
+
```
|
3414
|
+
|
3415
|
+
* <a name="hash-each"></a>
|
3416
|
+
Use `Hash#each_key` instead of `Hash#keys.each` and `Hash#each_value`
|
3417
|
+
instead of `Hash#values.each`.
|
3418
|
+
<sup>[[link](#hash-each)]</sup>
|
3419
|
+
|
3420
|
+
```Ruby
|
3421
|
+
# bad
|
3422
|
+
hash.keys.each { |k| p k }
|
3423
|
+
hash.values.each { |v| p v }
|
3424
|
+
hash.each { |k, _v| p k }
|
3425
|
+
hash.each { |_k, v| p v }
|
3426
|
+
|
3427
|
+
# good
|
3428
|
+
hash.each_key { |k| p k }
|
3429
|
+
hash.each_value { |v| p v }
|
3430
|
+
```
|
3431
|
+
|
3432
|
+
* <a name="hash-fetch"></a>
|
3433
|
+
Use `Hash#fetch` when dealing with hash keys that should be present.
|
3434
|
+
<sup>[[link](#hash-fetch)]</sup>
|
3435
|
+
|
3436
|
+
```Ruby
|
3437
|
+
heroes = { batman: 'Bruce Wayne', superman: 'Clark Kent' }
|
3438
|
+
# bad - if we make a mistake we might not spot it right away
|
3439
|
+
heroes[:batman] # => 'Bruce Wayne'
|
3440
|
+
heroes[:supermann] # => nil
|
3441
|
+
|
3442
|
+
# good - fetch raises a KeyError making the problem obvious
|
3443
|
+
heroes.fetch(:supermann)
|
3444
|
+
```
|
3445
|
+
|
3446
|
+
* <a name="hash-fetch-defaults"></a>
|
3447
|
+
Introduce default values for hash keys via `Hash#fetch` as opposed to using
|
3448
|
+
custom logic.
|
3449
|
+
<sup>[[link](#hash-fetch-defaults)]</sup>
|
3450
|
+
|
3451
|
+
```Ruby
|
3452
|
+
batman = { name: 'Bruce Wayne', is_evil: false }
|
3453
|
+
|
3454
|
+
# bad - if we just use || operator with falsy value we won't get the expected result
|
3455
|
+
batman[:is_evil] || true # => true
|
3456
|
+
|
3457
|
+
# good - fetch work correctly with falsy values
|
3458
|
+
batman.fetch(:is_evil, true) # => false
|
3459
|
+
```
|
3460
|
+
|
3461
|
+
* <a name="use-hash-blocks"></a>
|
3462
|
+
Prefer the use of the block instead of the default value in `Hash#fetch`
|
3463
|
+
if the code that has to be evaluated may have side effects or be expensive.
|
3464
|
+
<sup>[[link](#use-hash-blocks)]</sup>
|
3465
|
+
|
3466
|
+
```Ruby
|
3467
|
+
batman = { name: 'Bruce Wayne' }
|
3468
|
+
|
3469
|
+
# bad - if we use the default value, we eager evaluate it
|
3470
|
+
# so it can slow the program down if done multiple times
|
3471
|
+
batman.fetch(:powers, obtain_batman_powers) # obtain_batman_powers is an expensive call
|
3472
|
+
|
3473
|
+
# good - blocks are lazy evaluated, so only triggered in case of KeyError exception
|
3474
|
+
batman.fetch(:powers) { obtain_batman_powers }
|
3475
|
+
```
|
3476
|
+
|
3477
|
+
* <a name="hash-values-at"></a>
|
3478
|
+
Use `Hash#values_at` when you need to retrieve several values consecutively
|
3479
|
+
from a hash.
|
3480
|
+
<sup>[[link](#hash-values-at)]</sup>
|
3481
|
+
|
3482
|
+
```Ruby
|
3483
|
+
# bad
|
3484
|
+
email = data['email']
|
3485
|
+
username = data['nickname']
|
3486
|
+
|
3487
|
+
# good
|
3488
|
+
email, username = data.values_at('email', 'nickname')
|
3489
|
+
```
|
3490
|
+
|
3491
|
+
* <a name="ordered-hashes"></a>
|
3492
|
+
Rely on the fact that as of Ruby 1.9 hashes are ordered.
|
3493
|
+
<sup>[[link](#ordered-hashes)]</sup>
|
3494
|
+
|
3495
|
+
* <a name="no-modifying-collections"></a>
|
3496
|
+
Do not modify a collection while traversing it.
|
3497
|
+
<sup>[[link](#no-modifying-collections)]</sup>
|
3498
|
+
|
3499
|
+
* <a name="accessing-elements-directly"></a>
|
3500
|
+
When accessing elements of a collection, avoid direct access
|
3501
|
+
via `[n]` by using an alternate form of the reader method if it is
|
3502
|
+
supplied. This guards you from calling `[]` on `nil`.
|
3503
|
+
<sup>[[link](#accessing-elements-directly)]</sup>
|
3504
|
+
|
3505
|
+
```Ruby
|
3506
|
+
# bad
|
3507
|
+
Regexp.last_match[1]
|
3508
|
+
|
3509
|
+
# good
|
3510
|
+
Regexp.last_match(1)
|
3511
|
+
```
|
3512
|
+
|
3513
|
+
* <a name="provide-alternate-accessor-to-collections"></a>
|
3514
|
+
When providing an accessor for a collection, provide an alternate form
|
3515
|
+
to save users from checking for `nil` before accessing an element in
|
3516
|
+
the collection.
|
3517
|
+
<sup>[[link](#provide-alternate-accessor-to-collections)]</sup>
|
3518
|
+
|
3519
|
+
```Ruby
|
3520
|
+
# bad
|
3521
|
+
def awesome_things
|
3522
|
+
@awesome_things
|
3523
|
+
end
|
3524
|
+
|
3525
|
+
# good
|
3526
|
+
def awesome_things(index = nil)
|
3527
|
+
if index && @awesome_things
|
3528
|
+
@awesome_things[index]
|
3529
|
+
else
|
3530
|
+
@awesome_things
|
3531
|
+
end
|
3532
|
+
end
|
3533
|
+
```
|
3534
|
+
## Numbers
|
3535
|
+
|
3536
|
+
* <a name="integer-type-checking"></a>
|
3537
|
+
Use `Integer` check type of an integer number. Since `Fixnum` is
|
3538
|
+
platform-dependent, checking against it will return different results on
|
3539
|
+
32-bit and 64-bit machines.
|
3540
|
+
<sup>[[link](#integer-type-checking)]</sup>
|
3541
|
+
|
3542
|
+
```Ruby
|
3543
|
+
timestamp = Time.now.to_i
|
3544
|
+
|
3545
|
+
# bad
|
3546
|
+
timestamp.is_a? Fixnum
|
3547
|
+
timestamp.is_a? Bignum
|
3548
|
+
|
3549
|
+
# good
|
3550
|
+
timestamp.is_a? Integer
|
3551
|
+
```
|
3552
|
+
|
3553
|
+
* <a name="random-numbers"></a>
|
3554
|
+
Prefer to use ranges when generating random numbers instead of integers with offsets,
|
3555
|
+
since it clearly states your intentions. Imagine simulating a role of a dice:
|
3556
|
+
<sup>[[link](#random-numbers)]</sup>
|
3557
|
+
|
3558
|
+
```Ruby
|
3559
|
+
# bad
|
3560
|
+
rand(6) + 1
|
3561
|
+
|
3562
|
+
# good
|
3563
|
+
rand(1..6)
|
3564
|
+
```
|
3565
|
+
|
3566
|
+
## Strings
|
3567
|
+
|
3568
|
+
* <a name="string-interpolation"></a>
|
3569
|
+
Prefer string interpolation and string formatting instead of string
|
3570
|
+
concatenation:
|
3571
|
+
<sup>[[link](#string-interpolation)]</sup>
|
3572
|
+
|
3573
|
+
```Ruby
|
3574
|
+
# bad
|
3575
|
+
email_with_name = user.name + ' <' + user.email + '>'
|
3576
|
+
|
3577
|
+
# good
|
3578
|
+
email_with_name = "#{user.name} <#{user.email}>"
|
3579
|
+
|
3580
|
+
# good
|
3581
|
+
email_with_name = format('%s <%s>', user.name, user.email)
|
3582
|
+
```
|
3583
|
+
|
3584
|
+
* <a name="consistent-string-literals"></a>
|
3585
|
+
Adopt a consistent string literal quoting style. There are two popular
|
3586
|
+
styles in the Ruby community, both of which are considered good—single
|
3587
|
+
quotes by default (Option A) and double quotes by default (Option B).
|
3588
|
+
<sup>[[link](#consistent-string-literals)]</sup>
|
3589
|
+
|
3590
|
+
* **(Option A)** Prefer single-quoted strings when you don't need
|
3591
|
+
string interpolation or special symbols such as `\t`, `\n`, `'`,
|
3592
|
+
etc.
|
3593
|
+
|
3594
|
+
```Ruby
|
3595
|
+
# bad
|
3596
|
+
name = "Bozhidar"
|
3597
|
+
|
3598
|
+
# good
|
3599
|
+
name = 'Bozhidar'
|
3600
|
+
```
|
3601
|
+
|
3602
|
+
* **(Option B)** Prefer double-quotes unless your string literal
|
3603
|
+
contains `"` or escape characters you want to suppress.
|
3604
|
+
|
3605
|
+
```Ruby
|
3606
|
+
# bad
|
3607
|
+
name = 'Bozhidar'
|
3608
|
+
|
3609
|
+
# good
|
3610
|
+
name = "Bozhidar"
|
3611
|
+
```
|
3612
|
+
|
3613
|
+
The string literals in this guide are aligned with the first style.
|
3614
|
+
|
3615
|
+
* <a name="no-character-literals"></a>
|
3616
|
+
Don't use the character literal syntax `?x`. Since Ruby 1.9 it's basically
|
3617
|
+
redundant—`?x` would interpreted as `'x'` (a string with a single
|
3618
|
+
character in it).
|
3619
|
+
<sup>[[link](#no-character-literals)]</sup>
|
3620
|
+
|
3621
|
+
```Ruby
|
3622
|
+
# bad
|
3623
|
+
char = ?c
|
3624
|
+
|
3625
|
+
# good
|
3626
|
+
char = 'c'
|
3627
|
+
```
|
3628
|
+
|
3629
|
+
* <a name="curlies-interpolate"></a>
|
3630
|
+
Don't leave out `{}` around instance and global variables being interpolated
|
3631
|
+
into a string.
|
3632
|
+
<sup>[[link](#curlies-interpolate)]</sup>
|
3633
|
+
|
3634
|
+
```Ruby
|
3635
|
+
class Person
|
3636
|
+
attr_reader :first_name, :last_name
|
3637
|
+
|
3638
|
+
def initialize(first_name, last_name)
|
3639
|
+
@first_name = first_name
|
3640
|
+
@last_name = last_name
|
3641
|
+
end
|
3642
|
+
|
3643
|
+
# bad - valid, but awkward
|
3644
|
+
def to_s
|
3645
|
+
"#@first_name #@last_name"
|
3646
|
+
end
|
3647
|
+
|
3648
|
+
# good
|
3649
|
+
def to_s
|
3650
|
+
"#{@first_name} #{@last_name}"
|
3651
|
+
end
|
3652
|
+
end
|
3653
|
+
|
3654
|
+
$global = 0
|
3655
|
+
# bad
|
3656
|
+
puts "$global = #$global"
|
3657
|
+
|
3658
|
+
# good
|
3659
|
+
puts "$global = #{$global}"
|
3660
|
+
```
|
3661
|
+
|
3662
|
+
* <a name="no-to-s"></a>
|
3663
|
+
Don't use `Object#to_s` on interpolated objects. It's invoked on them
|
3664
|
+
automatically.
|
3665
|
+
<sup>[[link](#no-to-s)]</sup>
|
3666
|
+
|
3667
|
+
```Ruby
|
3668
|
+
# bad
|
3669
|
+
message = "This is the #{result.to_s}."
|
3670
|
+
|
3671
|
+
# good
|
3672
|
+
message = "This is the #{result}."
|
3673
|
+
```
|
3674
|
+
|
3675
|
+
* <a name="concat-strings"></a>
|
3676
|
+
Avoid using `String#+` when you need to construct large data chunks.
|
3677
|
+
Instead, use `String#<<`. Concatenation mutates the string instance in-place
|
3678
|
+
and is always faster than `String#+`, which creates a bunch of new string
|
3679
|
+
objects.
|
3680
|
+
<sup>[[link](#concat-strings)]</sup>
|
3681
|
+
|
3682
|
+
```Ruby
|
3683
|
+
# bad
|
3684
|
+
html = ''
|
3685
|
+
html += '<h1>Page title</h1>'
|
3686
|
+
|
3687
|
+
paragraphs.each do |paragraph|
|
3688
|
+
html += "<p>#{paragraph}</p>"
|
3689
|
+
end
|
3690
|
+
|
3691
|
+
# good and also fast
|
3692
|
+
html = ''
|
3693
|
+
html << '<h1>Page title</h1>'
|
3694
|
+
|
3695
|
+
paragraphs.each do |paragraph|
|
3696
|
+
html << "<p>#{paragraph}</p>"
|
3697
|
+
end
|
3698
|
+
```
|
3699
|
+
|
3700
|
+
* <a name="dont-abuse-gsub"></a>
|
3701
|
+
Don't use `String#gsub` in scenarios in which you can use a faster more specialized alternative.
|
3702
|
+
<sup>[[link](#dont-abuse-gsub)]</sup>
|
3703
|
+
|
3704
|
+
```Ruby
|
3705
|
+
url = 'http://example.com'
|
3706
|
+
str = 'lisp-case-rules'
|
3707
|
+
|
3708
|
+
# bad
|
3709
|
+
url.gsub('http://', 'https://')
|
3710
|
+
str.gsub('-', '_')
|
3711
|
+
|
3712
|
+
# good
|
3713
|
+
url.sub('http://', 'https://')
|
3714
|
+
str.tr('-', '_')
|
3715
|
+
```
|
3716
|
+
|
3717
|
+
* <a name="heredocs"></a>
|
3718
|
+
When using heredocs for multi-line strings keep in mind the fact that they
|
3719
|
+
preserve leading whitespace. It's a good practice to employ some margin based
|
3720
|
+
on which to trim the excessive whitespace.
|
3721
|
+
<sup>[[link](#heredocs)]</sup>
|
3722
|
+
|
3723
|
+
```Ruby
|
3724
|
+
code = <<-END.gsub(/^\s+\|/, '')
|
3725
|
+
|def test
|
3726
|
+
| some_method
|
3727
|
+
| other_method
|
3728
|
+
|end
|
3729
|
+
END
|
3730
|
+
# => "def test\n some_method\n other_method\nend\n"
|
3731
|
+
```
|
3732
|
+
|
3733
|
+
* <a name="squiggly-heredocs"></a>
|
3734
|
+
Use Ruby 2.3's squiggly heredocs for nicely indented multi-line strings.
|
3735
|
+
<sup>[[link](#squiggly-heredocs)]</sup>
|
3736
|
+
|
3737
|
+
```Ruby
|
3738
|
+
# bad - using Powerpack String#strip_margin
|
3739
|
+
code = <<-END.strip_margin('|')
|
3740
|
+
|def test
|
3741
|
+
| some_method
|
3742
|
+
| other_method
|
3743
|
+
|end
|
3744
|
+
END
|
3745
|
+
|
3746
|
+
# also bad
|
3747
|
+
code = <<-END
|
3748
|
+
def test
|
3749
|
+
some_method
|
3750
|
+
other_method
|
3751
|
+
end
|
3752
|
+
END
|
3753
|
+
|
3754
|
+
# good
|
3755
|
+
code = <<~END
|
3756
|
+
def test
|
3757
|
+
some_method
|
3758
|
+
other_method
|
3759
|
+
end
|
3760
|
+
END
|
3761
|
+
```
|
3762
|
+
|
3763
|
+
## Date & Time
|
3764
|
+
|
3765
|
+
* <a name="time-now"></a>
|
3766
|
+
Prefer `Time.now` over `Time.new` when retrieving the current system time.
|
3767
|
+
<sup>[[link](#time-now)]</sup>
|
3768
|
+
|
3769
|
+
* <a name="no-datetime"></a>
|
3770
|
+
Don't use `DateTime` unless you need to account for historical calendar
|
3771
|
+
reform -- and if you do, explicitly specify the `start` argument to
|
3772
|
+
clearly state your intentions.
|
3773
|
+
<sup>[[link](#no-datetime)]</sup>
|
3774
|
+
|
3775
|
+
```Ruby
|
3776
|
+
# bad - uses DateTime for current time
|
3777
|
+
DateTime.now
|
3778
|
+
|
3779
|
+
# good - uses Time for current time
|
3780
|
+
Time.now
|
3781
|
+
|
3782
|
+
# bad - uses DateTime for modern date
|
3783
|
+
DateTime.iso8601('2016-06-29')
|
3784
|
+
|
3785
|
+
# good - uses Date for modern date
|
3786
|
+
Date.iso8601('2016-06-29')
|
3787
|
+
|
3788
|
+
# good - uses DateTime with start argument for historical date
|
3789
|
+
DateTime.iso8601('1751-04-23', Date::ENGLAND)
|
3790
|
+
```
|
3791
|
+
|
3792
|
+
## Regular Expressions
|
3793
|
+
|
3794
|
+
> Some people, when confronted with a problem, think
|
3795
|
+
> "I know, I'll use regular expressions." Now they have two problems.<br>
|
3796
|
+
> -- Jamie Zawinski
|
3797
|
+
|
3798
|
+
* <a name="no-regexp-for-plaintext"></a>
|
3799
|
+
Don't use regular expressions if you just need plain text search in string:
|
3800
|
+
`string['text']`
|
3801
|
+
<sup>[[link](#no-regexp-for-plaintext)]</sup>
|
3802
|
+
|
3803
|
+
* <a name="regexp-string-index"></a>
|
3804
|
+
For simple constructions you can use regexp directly through string index.
|
3805
|
+
<sup>[[link](#regexp-string-index)]</sup>
|
3806
|
+
|
3807
|
+
```Ruby
|
3808
|
+
match = string[/regexp/] # get content of matched regexp
|
3809
|
+
first_group = string[/text(grp)/, 1] # get content of captured group
|
3810
|
+
string[/text (grp)/, 1] = 'replace' # string => 'text replace'
|
3811
|
+
```
|
3812
|
+
|
3813
|
+
* <a name="non-capturing-regexp"></a>
|
3814
|
+
Use non-capturing groups when you don't use the captured result.
|
3815
|
+
<sup>[[link](#non-capturing-regexp)]</sup>
|
3816
|
+
|
3817
|
+
```Ruby
|
3818
|
+
# bad
|
3819
|
+
/(first|second)/
|
3820
|
+
|
3821
|
+
# good
|
3822
|
+
/(?:first|second)/
|
3823
|
+
```
|
3824
|
+
|
3825
|
+
* <a name="no-perl-regexp-last-matchers"></a>
|
3826
|
+
Don't use the cryptic Perl-legacy variables denoting last regexp group
|
3827
|
+
matches (`$1`, `$2`, etc). Use `Regexp.last_match(n)` instead.
|
3828
|
+
<sup>[[link](#no-perl-regexp-last-matchers)]</sup>
|
3829
|
+
|
3830
|
+
```Ruby
|
3831
|
+
/(regexp)/ =~ string
|
3832
|
+
...
|
3833
|
+
|
3834
|
+
# bad
|
3835
|
+
process $1
|
3836
|
+
|
3837
|
+
# good
|
3838
|
+
process Regexp.last_match(1)
|
3839
|
+
```
|
3840
|
+
|
3841
|
+
* <a name="no-numbered-regexes"></a>
|
3842
|
+
Avoid using numbered groups as it can be hard to track what they contain.
|
3843
|
+
Named groups can be used instead.
|
3844
|
+
<sup>[[link](#no-numbered-regexes)]</sup>
|
3845
|
+
|
3846
|
+
```Ruby
|
3847
|
+
# bad
|
3848
|
+
/(regexp)/ =~ string
|
3849
|
+
# some code
|
3850
|
+
process Regexp.last_match(1)
|
3851
|
+
|
3852
|
+
# good
|
3853
|
+
/(?<meaningful_var>regexp)/ =~ string
|
3854
|
+
# some code
|
3855
|
+
process meaningful_var
|
3856
|
+
```
|
3857
|
+
|
3858
|
+
* <a name="limit-escapes"></a>
|
3859
|
+
Character classes have only a few special characters you should care about:
|
3860
|
+
`^`, `-`, `\`, `]`, so don't escape `.` or brackets in `[]`.
|
3861
|
+
<sup>[[link](#limit-escapes)]</sup>
|
3862
|
+
|
3863
|
+
* <a name="caret-and-dollar-regexp"></a>
|
3864
|
+
Be careful with `^` and `$` as they match start/end of line, not string
|
3865
|
+
endings. If you want to match the whole string use: `\A` and `\z` (not to be
|
3866
|
+
confused with `\Z` which is the equivalent of `/\n?\z/`).
|
3867
|
+
<sup>[[link](#caret-and-dollar-regexp)]</sup>
|
3868
|
+
|
3869
|
+
```Ruby
|
3870
|
+
string = "some injection\nusername"
|
3871
|
+
string[/^username$/] # matches
|
3872
|
+
string[/\Ausername\z/] # doesn't match
|
3873
|
+
```
|
3874
|
+
|
3875
|
+
* <a name="comment-regexes"></a>
|
3876
|
+
Use `x` modifier for complex regexps. This makes them more readable and you
|
3877
|
+
can add some useful comments. Just be careful as spaces are ignored.
|
3878
|
+
<sup>[[link](#comment-regexes)]</sup>
|
3879
|
+
|
3880
|
+
```Ruby
|
3881
|
+
regexp = /
|
3882
|
+
start # some text
|
3883
|
+
\s # white space char
|
3884
|
+
(group) # first group
|
3885
|
+
(?:alt1|alt2) # some alternation
|
3886
|
+
end
|
3887
|
+
/x
|
3888
|
+
```
|
3889
|
+
|
3890
|
+
* <a name="gsub-blocks"></a>
|
3891
|
+
For complex replacements `sub`/`gsub` can be used with a block or a hash.
|
3892
|
+
<sup>[[link](#gsub-blocks)]</sup>
|
3893
|
+
|
3894
|
+
```Ruby
|
3895
|
+
words = 'foo bar'
|
3896
|
+
words.sub(/f/, 'f' => 'F') # => 'Foo bar'
|
3897
|
+
words.gsub(/\w+/) { |word| word.capitalize } # => 'Foo Bar'
|
3898
|
+
```
|
3899
|
+
|
3900
|
+
## Percent Literals
|
3901
|
+
|
3902
|
+
* <a name="percent-q-shorthand"></a>
|
3903
|
+
Use `%()`(it's a shorthand for `%Q`) for single-line strings which require
|
3904
|
+
both interpolation and embedded double-quotes. For multi-line strings, prefer
|
3905
|
+
heredocs.
|
3906
|
+
<sup>[[link](#percent-q-shorthand)]</sup>
|
3907
|
+
|
3908
|
+
```Ruby
|
3909
|
+
# bad (no interpolation needed)
|
3910
|
+
%(<div class="text">Some text</div>)
|
3911
|
+
# should be '<div class="text">Some text</div>'
|
3912
|
+
|
3913
|
+
# bad (no double-quotes)
|
3914
|
+
%(This is #{quality} style)
|
3915
|
+
# should be "This is #{quality} style"
|
3916
|
+
|
3917
|
+
# bad (multiple lines)
|
3918
|
+
%(<div>\n<span class="big">#{exclamation}</span>\n</div>)
|
3919
|
+
# should be a heredoc.
|
3920
|
+
|
3921
|
+
# good (requires interpolation, has quotes, single line)
|
3922
|
+
%(<tr><td class="name">#{name}</td>)
|
3923
|
+
```
|
3924
|
+
|
3925
|
+
* <a name="percent-q"></a>
|
3926
|
+
Avoid %() or the equivalent %q() unless you have a string with both `'` and
|
3927
|
+
`"` in it. Regular string literals are more readable and should be preferred
|
3928
|
+
unless a lot of characters would have to be escaped in them.
|
3929
|
+
<sup>[[link](#percent-q)]</sup>
|
3930
|
+
|
3931
|
+
```Ruby
|
3932
|
+
# bad
|
3933
|
+
name = %q(Bruce Wayne)
|
3934
|
+
time = %q(8 o'clock)
|
3935
|
+
question = %q("What did you say?")
|
3936
|
+
|
3937
|
+
# good
|
3938
|
+
name = 'Bruce Wayne'
|
3939
|
+
time = "8 o'clock"
|
3940
|
+
question = '"What did you say?"'
|
3941
|
+
quote = %q(<p class='quote'>"What did you say?"</p>)
|
3942
|
+
```
|
3943
|
+
|
3944
|
+
* <a name="percent-r"></a>
|
3945
|
+
Use `%r` only for regular expressions matching *at least* one '/'
|
3946
|
+
character.
|
3947
|
+
<sup>[[link](#percent-r)]</sup>
|
3948
|
+
|
3949
|
+
```Ruby
|
3950
|
+
# bad
|
3951
|
+
%r{\s+}
|
3952
|
+
|
3953
|
+
# good
|
3954
|
+
%r{^/(.*)$}
|
3955
|
+
%r{^/blog/2011/(.*)$}
|
3956
|
+
```
|
3957
|
+
|
3958
|
+
* <a name="percent-x"></a>
|
3959
|
+
Avoid the use of `%x` unless you're going to invoke a command with
|
3960
|
+
backquotes in it(which is rather unlikely).
|
3961
|
+
<sup>[[link](#percent-x)]</sup>
|
3962
|
+
|
3963
|
+
```Ruby
|
3964
|
+
# bad
|
3965
|
+
date = %x(date)
|
3966
|
+
|
3967
|
+
# good
|
3968
|
+
date = `date`
|
3969
|
+
echo = %x(echo `date`)
|
3970
|
+
```
|
3971
|
+
|
3972
|
+
* <a name="percent-s"></a>
|
3973
|
+
Avoid the use of `%s`. It seems that the community has decided `:"some
|
3974
|
+
string"` is the preferred way to create a symbol with spaces in it.
|
3975
|
+
<sup>[[link](#percent-s)]</sup>
|
3976
|
+
|
3977
|
+
* <a name="percent-literal-braces"></a>
|
3978
|
+
Use the braces that are the most appropriate for the various kinds of percent
|
3979
|
+
literals.
|
3980
|
+
<sup>[[link](#percent-literal-braces)]</sup>
|
3981
|
+
- `()` for string literals(`%q`, `%Q`).
|
3982
|
+
- `[]` for array literals(`%w`, `%i`, `%W`, `%I`) as it is aligned with
|
3983
|
+
the standard array literals.
|
3984
|
+
- `{}` for regexp literals(`%r`) since parentheses often appear inside regular
|
3985
|
+
expressions. That's why a less common character with `{` is usually the best
|
3986
|
+
delimiter for `%r` literals.
|
3987
|
+
- `()` for all other literals (e.g. `%s`, `%x`)
|
3988
|
+
|
3989
|
+
```Ruby
|
3990
|
+
# bad
|
3991
|
+
%q{"Test's king!", John said.}
|
3992
|
+
|
3993
|
+
# good
|
3994
|
+
%q("Test's king!", John said.)
|
3995
|
+
|
3996
|
+
# bad
|
3997
|
+
%w(one two three)
|
3998
|
+
%i(one two three)
|
3999
|
+
|
4000
|
+
# good
|
4001
|
+
%w[one two three]
|
4002
|
+
%i[one two three]
|
4003
|
+
|
4004
|
+
# bad
|
4005
|
+
%r((\w+)-(\d+))
|
4006
|
+
%r{\w{1,2}\d{2,5}}
|
4007
|
+
|
4008
|
+
# good
|
4009
|
+
%r{(\w+)-(\d+)}
|
4010
|
+
%r|\w{1,2}\d{2,5}|
|
4011
|
+
```
|
4012
|
+
|
4013
|
+
## Metaprogramming
|
4014
|
+
|
4015
|
+
* <a name="no-needless-metaprogramming"></a>
|
4016
|
+
Avoid needless metaprogramming.
|
4017
|
+
<sup>[[link](#no-needless-metaprogramming)]</sup>
|
4018
|
+
|
4019
|
+
* <a name="no-monkey-patching"></a>
|
4020
|
+
Do not mess around in core classes when writing libraries. (Do not
|
4021
|
+
monkey-patch them.)
|
4022
|
+
<sup>[[link](#no-monkey-patching)]</sup>
|
4023
|
+
|
4024
|
+
* <a name="block-class-eval"></a>
|
4025
|
+
The block form of `class_eval` is preferable to the string-interpolated
|
4026
|
+
form.
|
4027
|
+
<sup>[[link](#block-class-eval)]</sup>
|
4028
|
+
|
4029
|
+
- when you use the string-interpolated form, always supply `__FILE__`
|
4030
|
+
and `__LINE__`, so that your backtraces make sense:
|
4031
|
+
|
4032
|
+
```ruby
|
4033
|
+
class_eval 'def use_relative_model_naming?; true; end', __FILE__, __LINE__
|
4034
|
+
```
|
4035
|
+
|
4036
|
+
- `define_method` is preferable to `class_eval{ def ... }`
|
4037
|
+
|
4038
|
+
* <a name="eval-comment-docs"></a>
|
4039
|
+
When using `class_eval` (or other `eval`) with string interpolation, add a
|
4040
|
+
comment block showing its appearance if interpolated (a practice used in Rails
|
4041
|
+
code):
|
4042
|
+
<sup>[[link](#eval-comment-docs)]</sup>
|
4043
|
+
|
4044
|
+
```ruby
|
4045
|
+
# from activesupport/lib/active_support/core_ext/string/output_safety.rb
|
4046
|
+
UNSAFE_STRING_METHODS.each do |unsafe_method|
|
4047
|
+
if 'String'.respond_to?(unsafe_method)
|
4048
|
+
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
4049
|
+
def #{unsafe_method}(*params, &block) # def capitalize(*params, &block)
|
4050
|
+
to_str.#{unsafe_method}(*params, &block) # to_str.capitalize(*params, &block)
|
4051
|
+
end # end
|
4052
|
+
|
4053
|
+
def #{unsafe_method}!(*params) # def capitalize!(*params)
|
4054
|
+
@dirty = true # @dirty = true
|
4055
|
+
super # super
|
4056
|
+
end # end
|
4057
|
+
EOT
|
4058
|
+
end
|
4059
|
+
end
|
4060
|
+
```
|
4061
|
+
|
4062
|
+
* <a name="no-method-missing"></a>
|
4063
|
+
Avoid using `method_missing` for metaprogramming because backtraces become
|
4064
|
+
messy, the behavior is not listed in `#methods`, and misspelled method calls
|
4065
|
+
might silently work, e.g. `nukes.launch_state = false`. Consider using
|
4066
|
+
delegation, proxy, or `define_method` instead. If you must use
|
4067
|
+
`method_missing`:
|
4068
|
+
<sup>[[link](#no-method-missing)]</sup>
|
4069
|
+
|
4070
|
+
- Be sure to [also define `respond_to_missing?`](http://blog.marc-andre.ca/2010/11/methodmissing-politely.html)
|
4071
|
+
- Only catch methods with a well-defined prefix, such as `find_by_*` -- make your code as assertive as possible.
|
4072
|
+
- Call `super` at the end of your statement
|
4073
|
+
- Delegate to assertive, non-magical methods:
|
4074
|
+
|
4075
|
+
```ruby
|
4076
|
+
# bad
|
4077
|
+
def method_missing?(meth, *params, &block)
|
4078
|
+
if /^find_by_(?<prop>.*)/ =~ meth
|
4079
|
+
# ... lots of code to do a find_by
|
4080
|
+
else
|
4081
|
+
super
|
4082
|
+
end
|
4083
|
+
end
|
4084
|
+
|
4085
|
+
# good
|
4086
|
+
def method_missing?(meth, *params, &block)
|
4087
|
+
if /^find_by_(?<prop>.*)/ =~ meth
|
4088
|
+
find_by(prop, *params, &block)
|
4089
|
+
else
|
4090
|
+
super
|
4091
|
+
end
|
4092
|
+
end
|
4093
|
+
|
4094
|
+
# best of all, though, would to define_method as each findable attribute is declared
|
4095
|
+
```
|
4096
|
+
|
4097
|
+
* <a name="prefer-public-send"></a>
|
4098
|
+
Prefer `public_send` over `send` so as not to circumvent `private`/`protected` visibility.
|
4099
|
+
<sup>[[link](#prefer-public-send)]</sup>
|
4100
|
+
|
4101
|
+
```ruby
|
4102
|
+
# We have an ActiveModel Organization that includes concern Activatable
|
4103
|
+
module Activatable
|
4104
|
+
extend ActiveSupport::Concern
|
4105
|
+
|
4106
|
+
included do
|
4107
|
+
before_create :create_token
|
4108
|
+
end
|
4109
|
+
|
4110
|
+
private
|
4111
|
+
|
4112
|
+
def reset_token
|
4113
|
+
# some code
|
4114
|
+
end
|
4115
|
+
|
4116
|
+
def create_token
|
4117
|
+
# some code
|
4118
|
+
end
|
4119
|
+
|
4120
|
+
def activate!
|
4121
|
+
# some code
|
4122
|
+
end
|
4123
|
+
end
|
4124
|
+
|
4125
|
+
class Organization < ActiveRecord::Base
|
4126
|
+
include Activatable
|
4127
|
+
end
|
4128
|
+
|
4129
|
+
linux_organization = Organization.find(...)
|
4130
|
+
# BAD - violates privacy
|
4131
|
+
linux_organization.send(:reset_token)
|
4132
|
+
# GOOD - should throw an exception
|
4133
|
+
linux_organization.public_send(:reset_token)
|
4134
|
+
```
|
4135
|
+
|
4136
|
+
* <a name="prefer-__send__"></a>
|
4137
|
+
Prefer `__send__` over `send`, as `send` may overlap with existing methods.
|
4138
|
+
<sup>[[link](#prefer-__send__)]</sup>
|
4139
|
+
|
4140
|
+
```ruby
|
4141
|
+
require 'socket'
|
4142
|
+
|
4143
|
+
u1 = UDPSocket.new
|
4144
|
+
u1.bind('127.0.0.1', 4913)
|
4145
|
+
u2 = UDPSocket.new
|
4146
|
+
u2.connect('127.0.0.1', 4913)
|
4147
|
+
# Won't send a message to the receiver obj.
|
4148
|
+
# Instead it will send a message via UDP socket.
|
4149
|
+
u2.send :sleep, 0
|
4150
|
+
# Will actually send a message to the receiver obj.
|
4151
|
+
u2.__send__ ...
|
4152
|
+
```
|
4153
|
+
|
4154
|
+
## Misc
|
4155
|
+
|
4156
|
+
* <a name="always-warn"></a>
|
4157
|
+
Write `ruby -w` safe code.
|
4158
|
+
<sup>[[link](#always-warn)]</sup>
|
4159
|
+
|
4160
|
+
* <a name="no-optional-hash-params"></a>
|
4161
|
+
Avoid hashes as optional parameters. Does the method do too much? (Object
|
4162
|
+
initializers are exceptions for this rule).
|
4163
|
+
<sup>[[link](#no-optional-hash-params)]</sup>
|
4164
|
+
|
4165
|
+
* <a name="short-methods"></a>
|
4166
|
+
Avoid methods longer than 10 LOC (lines of code). Ideally, most methods will
|
4167
|
+
be shorter than 5 LOC. Empty lines do not contribute to the relevant LOC.
|
4168
|
+
<sup>[[link](#short-methods)]</sup>
|
4169
|
+
|
4170
|
+
* <a name="too-many-params"></a>
|
4171
|
+
Avoid parameter lists longer than three or four parameters.
|
4172
|
+
<sup>[[link](#too-many-params)]</sup>
|
4173
|
+
|
4174
|
+
* <a name="private-global-methods"></a>
|
4175
|
+
If you really need "global" methods, add them to Kernel and make them
|
4176
|
+
private.
|
4177
|
+
<sup>[[link](#private-global-methods)]</sup>
|
4178
|
+
|
4179
|
+
* <a name="instance-vars"></a>
|
4180
|
+
Use module instance variables instead of global variables.
|
4181
|
+
<sup>[[link](#instance-vars)]</sup>
|
4182
|
+
|
4183
|
+
```Ruby
|
4184
|
+
# bad
|
4185
|
+
$foo_bar = 1
|
4186
|
+
|
4187
|
+
# good
|
4188
|
+
module Foo
|
4189
|
+
class << self
|
4190
|
+
attr_accessor :bar
|
4191
|
+
end
|
4192
|
+
end
|
4193
|
+
|
4194
|
+
Foo.bar = 1
|
4195
|
+
```
|
4196
|
+
|
4197
|
+
* <a name="optionparser"></a>
|
4198
|
+
Use `OptionParser` for parsing complex command line options and `ruby -s`
|
4199
|
+
for trivial command line options.
|
4200
|
+
<sup>[[link](#optionparser)]</sup>
|
4201
|
+
|
4202
|
+
* <a name="functional-code"></a>
|
4203
|
+
Code in a functional way, avoiding mutation when that makes sense.
|
4204
|
+
<sup>[[link](#functional-code)]</sup>
|
4205
|
+
|
4206
|
+
* <a name="no-param-mutations"></a>
|
4207
|
+
Do not mutate parameters unless that is the purpose of the method.
|
4208
|
+
<sup>[[link](#no-param-mutations)]</sup>
|
4209
|
+
|
4210
|
+
* <a name="three-is-the-number-thou-shalt-count"></a>
|
4211
|
+
Avoid more than three levels of block nesting.
|
4212
|
+
<sup>[[link](#three-is-the-number-thou-shalt-count)]</sup>
|
4213
|
+
|
4214
|
+
* <a name="be-consistent"></a>
|
4215
|
+
Be consistent. In an ideal world, be consistent with these guidelines.
|
4216
|
+
<sup>[[link](#be-consistent)]</sup>
|
4217
|
+
|
4218
|
+
* <a name="common-sense"></a>
|
4219
|
+
Use common sense.
|
4220
|
+
<sup>[[link](#common-sense)]</sup>
|
4221
|
+
|
4222
|
+
# Contributing
|
4223
|
+
|
4224
|
+
You can financially support bbatsov's original style guide (and RuboCop) with contributions via [Gratipay](https://gratipay.com/~bbatsov/).
|
4225
|
+
|
4226
|
+
[![Support via Gratipay](https://cdn.rawgit.com/gratipay/gratipay-badge/2.3.0/dist/gratipay.png)](https://gratipay.com/~bbatsov/)
|
4227
|
+
|
4228
|
+
## How to Contribute?
|
4229
|
+
|
4230
|
+
It's easy, just follow the [contribution guidelines](https://github.com/voxable-labs/ruby-style-guide/blob/master/CONTRIBUTING.md).
|
4231
|
+
|
4232
|
+
# License
|
4233
|
+
|
4234
|
+
![Creative Commons License](http://i.creativecommons.org/l/by/3.0/88x31.png)
|
4235
|
+
This work is licensed under a [Creative Commons Attribution 3.0 Unported License](http://creativecommons.org/licenses/by/3.0/deed.en_US). This is a fork of [the original work](https://github.com/bbatsov/ruby-style-guide), with some changes.
|