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