|
| 1 | +# Ruby reference and examples |
| 2 | + |
| 3 | +## [Conditional modifiers](#conditional-modifiers) |
| 4 | + |
| 5 | +Avoid conditional modifiers (lines that end with conditionals): |
| 6 | + |
| 7 | +```ruby |
| 8 | + # unfavorable choice |
| 9 | + user.first_name if user.present? |
| 10 | + |
| 11 | + # preferred choice |
| 12 | + if user.present? |
| 13 | + user.first_name |
| 14 | + end |
| 15 | +``` |
| 16 | + |
| 17 | +## [Multiple assignments](#multiple-assignments) |
| 18 | + |
| 19 | +Avoid multiple assignments per line. |
| 20 | + |
| 21 | +- Reading requires scanning back and forth across the line |
| 22 | +- Adding more assignments causes modifications instead of additions |
| 23 | +- Hides complexity |
| 24 | +- Easy to miss when scanning a method |
| 25 | + |
| 26 | +```ruby |
| 27 | + # unfavorable choice |
| 28 | + breakfast, lunch = :pancakes, :spaghetti |
| 29 | + |
| 30 | + # preferred choice |
| 31 | + breakfast = :pancakes |
| 32 | + lunch = :spaghetti |
| 33 | +``` |
| 34 | + |
| 35 | +## [Organizational comments](#organizational-comments) |
| 36 | + |
| 37 | +Avoid organizational comments: |
| 38 | + |
| 39 | +```ruby |
| 40 | + # unfavorable choice |
| 41 | + # Validations |
| 42 | + validate_presence_of :user |
| 43 | + |
| 44 | + # preferred choice |
| 45 | + validate_presence_of :user |
| 46 | +``` |
| 47 | + |
| 48 | +## [Ternary operators](#ternary-operators) |
| 49 | + |
| 50 | +Avoid ternary operators. Use multi-line `if` instead to emphasize code branches. |
| 51 | + |
| 52 | +```ruby |
| 53 | + # unfavorable choice |
| 54 | + user.present? ? user.first_name : "Unknown user" |
| 55 | + |
| 56 | + # preferred choice |
| 57 | + if user.present? |
| 58 | + user.first_name |
| 59 | + else |
| 60 | + "Unknown user" |
| 61 | + end |
| 62 | +``` |
| 63 | + |
| 64 | +## [Bang method names](#bang-method-names) |
| 65 | + |
| 66 | +Avoid bang (!) method names. Prefer descriptive names. |
| 67 | +Example: in a method like 'invite!`, it is unclear if the author is going to |
| 68 | +modify the user, raise an exception, or do something else. |
| 69 | + |
| 70 | +```ruby |
| 71 | + # unfavorable choice |
| 72 | + def invite! |
| 73 | + |
| 74 | + # preferred choice |
| 75 | + def send_invitation_email |
| 76 | +``` |
| 77 | + |
| 78 | + |
| 79 | + |
| 80 | + |
| 81 | + |
| 82 | + |
| 83 | +* Avoid `%q`, `%Q`, `%x`, `%s`, and `%W`. |
| 84 | +* Avoid hashes as optional parameters. Does the method do too much? |
| 85 | +* Avoid including code and gems in source control that are specific to your |
| 86 | + development machine or process. Examples: `.rvmrc`, file watchers, debuggers. |
| 87 | +* Avoid meta-programming. |
| 88 | +* Avoid monkey-patching core classes. |
| 89 | +* Avoid `return` unless required. |
| 90 | +* Avoid superfluous parentheses when calling methods, but keep them when you |
| 91 | + assign the return value. |
| 92 | + x = Math.sin(y) |
| 93 | + array.delete e |
| 94 | +* Avoid ternary operators (`boolean ? true : false`). Use multi-line `if` |
| 95 | + instead to emphasize code branches. |
| 96 | +* Define the version of Ruby the project uses in the Gemfile. |
| 97 | +* Don't use `unless`. |
| 98 | +* Prefer classes to modules when designing functionality that is shared by |
| 99 | + multiple models. |
| 100 | +* Prefer `detect` over `find` and `select` over `find_all` to avoid confusion |
| 101 | + with ActiveRecord and keep `select`/`reject` symmetry. |
| 102 | +* Prefer `map` over `collect` and `reduce` over `inject` due to symmetry and |
| 103 | + familarity with mapping and reducing in other technologies. |
| 104 | +* Use `_` for unused block parameters. |
| 105 | + hash.map { |_, v| v + 1 } |
| 106 | +* Use `%{}` for single-line strings needing interpolation and double-quotes. |
| 107 | +* Use `%w()` over `['', '']` for an array of words. |
| 108 | +* Use `&&` and `||` for boolean expressions. |
| 109 | +* Use `||=` freely. |
| 110 | +* Use `{...}` over `do..end` for single-line blocks. |
| 111 | +* Use `!` suffix for dangerous methods (modifies `self`). |
| 112 | +* Use `?` suffix for predicate methods (return a boolean). |
| 113 | +* Use `CamelCase` for classes and modules, `snake_case` for variables and |
| 114 | + methods, `SCREAMING_SNAKE_CASE` for constants. |
| 115 | +* Use `def` with parentheses when there are arguments. |
| 116 | +* Use `do..end` over `{...}` for multi-line blocks. |
| 117 | +* Use `each`, not `for`, for iteration. |
| 118 | +* Use heredocs for multi-line strings. |
| 119 | +* Use `/(?:first|second)/` over `/(first|second)/` when you don't need the |
| 120 | + captured group. |
| 121 | +* Use `private` over `protected` to indicate scope. |
| 122 | +* Use `def self.method` over `def Class.method` or `class << self`. |
| 123 | +* Use `Set` over `Array` for arrays with unique elements. The lookup is faster. |
| 124 | +* Use single-quotes for strings unless interpolating. |
| 125 | +* Use `unless boolean?` instead of `if !boolean?`. |
| 126 | +* Use [Factory Girl](https://github.com/thoughtbot/factory_girl) for setting up |
| 127 | + complicated test data. |
0 commit comments