Skip to content

[WIP] Ruby main page guide #741

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions ruby/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
# Ruby

[Sample 1](sample_1.rb) [Sample 2](sample_2.rb)
- [How to](how-to.md)
- [Sample 1](sample_1.rb)
- [Sample 2](sample_2.rb)

- Use [standard]
- Avoid conditional modifiers (lines that end with conditionals). [36491dbb9]
- Avoid multiple assignments per line (`one, two = 1, 2`). [#109]
- Avoid organizational comments (`# Validations`). [#63]
- Avoid ternary operators (`boolean ? true : false`). Use multi-line `if`
instead to emphasize code branches. [36491dbb9]
- Avoid bang (!) method names. Prefer descriptive names. [#122]
---

- [Avoid conditional modifiers (lines that end with conditionals)](how-to.md#conditional-modifiers)
- [Avoid multiple assignments per line](how-to.md#multiple-assignments)
- [Avoid organizational comments](how-to.md#organizational-comments)
- [Avoid ternary operators. Use multi-line `if` instead to emphasize code branches](how-to.md#ternary-operators)
- [Avoid bang (!) method names. Prefer descriptive names](how-to.md#bang-method-names)
- [Use `_` for unused block parameters](how-to.md#unused-block-params)
- [Prefix unused variables or parameters with underscore](how-to.md#unused-variables)


---

- Avoid optional parameters. Does the method do too much?
- Avoid monkey-patching.
- Name variables created by a factory after the factory (`user_factory` creates
`user`).
- Prefer nested class and module definitions over the shorthand version
Expand All @@ -19,8 +29,7 @@
- Prefer `reduce` over `inject`. [#237]
- Prefer `&:method_name` to `{ |item| item.method_name }` for simple method
calls. [#183]
- Use `_` for unused block parameters. [0d819844]
- Prefix unused variables or parameters with underscore (`_`). [#335]

- Suffix variables holding a factory with `_factory` (`user_factory`).
- Use a leading underscore when defining instance variables for memoization.
[#373]
Expand All @@ -30,10 +39,9 @@
- Use `def self.method`, not `class << self`. [40090e22]
- Use `def` with parentheses when there are arguments. [36491dbb9]
- Use heredocs for multi-line strings. [36491dbb9]
- Use [standard]
- Order class methods above instance methods. [#320]
- Prefer method invocation over instance variables. [#331]
- Avoid optional parameters. Does the method do too much?
- Avoid monkey-patching.
- Generate necessary [Bundler binstubs] for the project, such as `rake` and
`rspec`, and add them to version control.
- Prefer classes to modules when designing functionality that is shared by
Expand All @@ -42,15 +50,11 @@
methods like `def ==(other)`, `def <(other)`, and `def >(other)`.

[standard]: https://github.com/testdouble/standard
[#63]: https://github.com/thoughtbot/guides/pull/63
[#109]: https://github.com/thoughtbot/guides/pull/109
[#122]: https://github.com/thoughtbot/guides/pull/122
[#183]: https://github.com/thoughtbot/guides/pull/183
[#237]: https://github.com/thoughtbot/guides/pull/237
[#320]: https://github.com/thoughtbot/guides/pull/320
[#331]: https://github.com/thoughtbot/guides/pull/331
[#332]: https://github.com/thoughtbot/guides/pull/332
[#335]: https://github.com/thoughtbot/guides/pull/335
[#373]: https://github.com/thoughtbot/guides/pull/373
[0d819844]: https://github.com/thoughtbot/guides/commit/0d819844
[36491dbb9]: https://github.com/thoughtbot/guides/commit/36491dbb9
Expand Down
147 changes: 147 additions & 0 deletions ruby/how-to.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Ruby reference and examples

## [Conditional modifiers](#conditional-modifiers)

Avoid conditional modifiers (lines that end with conditionals):

```ruby
# unfavorable choice
user.first_name if user.present?

# preferred choice
if user.present?
user.first_name
end
```

## [Multiple assignments](#multiple-assignments)

Avoid multiple assignments per line.

- Reading requires scanning back and forth across the line
- Adding more assignments causes modifications instead of additions
- Hides complexity
- Easy to miss when scanning a method

```ruby
# unfavorable choice
breakfast, lunch = :pancakes, :spaghetti

# preferred choice
breakfast = :pancakes
lunch = :spaghetti
```

## [Organizational comments](#organizational-comments)

Avoid organizational comments:

```ruby
# unfavorable choice
# Validations
validate_presence_of :user

# preferred choice
validate_presence_of :user
```

## [Ternary operators](#ternary-operators)

Avoid ternary operators. Use multi-line `if` instead to emphasize code branches.

```ruby
# unfavorable choice
user.present? ? user.first_name : "Unknown user"

# preferred choice
if user.present?
user.first_name
else
"Unknown user"
end
```

## [Bang method names](#bang-method-names)

Avoid bang (!) method names. Prefer descriptive names.

Example: in a method like 'invite!`, it is unclear if the author is going to
modify the user, raise an exception, or do something else.

```ruby
# unfavorable choice
def invite!

# preferred choice
def send_invitation_email
```

## [Unused block parameters](#unused-block-params)

Check failure on line 79 in ruby/how-to.md

View workflow job for this annotation

GitHub Actions / lint

Link fragments should be valid

ruby/how-to.md:79:4 MD051/link-fragments Link fragments should be valid [Context: "[Unused block parameters](#unused-block-params)"] https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md051.md

```ruby
# unfavorable choice
hash.map { |key, value| v + 1 }

# preferred choice
hash.map { |_, value| value + 1 }
hash.map { |_key, v| v + 1 }
```

## [Unused variables](#unused-variables)

```ruby
# unfavorable choice
user = create(:user)

# preferred choice
_user = create(:user)
```


Check failure on line 100 in ruby/how-to.md

View workflow job for this annotation

GitHub Actions / lint

Multiple consecutive blank lines

ruby/how-to.md:100 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2] https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md012.md

Check failure on line 101 in ruby/how-to.md

View workflow job for this annotation

GitHub Actions / lint

Multiple consecutive blank lines

ruby/how-to.md:101 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 3] https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md012.md

Check failure on line 102 in ruby/how-to.md

View workflow job for this annotation

GitHub Actions / lint

Multiple consecutive blank lines

ruby/how-to.md:102 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 4] https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md012.md
---

* Avoid `%q`, `%Q`, `%x`, `%s`, and `%W`.

Check failure on line 105 in ruby/how-to.md

View workflow job for this annotation

GitHub Actions / lint

Unordered list style

ruby/how-to.md:105:1 MD004/ul-style Unordered list style [Expected: dash; Actual: asterisk] https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md004.md
* Avoid hashes as optional parameters. Does the method do too much?

Check failure on line 106 in ruby/how-to.md

View workflow job for this annotation

GitHub Actions / lint

Unordered list style

ruby/how-to.md:106:1 MD004/ul-style Unordered list style [Expected: dash; Actual: asterisk] https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md004.md
* Avoid including code and gems in source control that are specific to your

Check failure on line 107 in ruby/how-to.md

View workflow job for this annotation

GitHub Actions / lint

Unordered list style

ruby/how-to.md:107:1 MD004/ul-style Unordered list style [Expected: dash; Actual: asterisk] https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md004.md
development machine or process. Examples: `.rvmrc`, file watchers, debuggers.
* Avoid meta-programming.

Check failure on line 109 in ruby/how-to.md

View workflow job for this annotation

GitHub Actions / lint

Unordered list style

ruby/how-to.md:109:1 MD004/ul-style Unordered list style [Expected: dash; Actual: asterisk] https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md004.md
* Avoid monkey-patching core classes.

Check failure on line 110 in ruby/how-to.md

View workflow job for this annotation

GitHub Actions / lint

Unordered list style

ruby/how-to.md:110:1 MD004/ul-style Unordered list style [Expected: dash; Actual: asterisk] https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md004.md
* Avoid `return` unless required.

Check failure on line 111 in ruby/how-to.md

View workflow job for this annotation

GitHub Actions / lint

Unordered list style

ruby/how-to.md:111:1 MD004/ul-style Unordered list style [Expected: dash; Actual: asterisk] https://github.com/DavidAnson/markdownlint/blob/v0.37.4/doc/md004.md
* Avoid superfluous parentheses when calling methods, but keep them when you
assign the return value.
x = Math.sin(y)
array.delete e
* Avoid ternary operators (`boolean ? true : false`). Use multi-line `if`
instead to emphasize code branches.
* Define the version of Ruby the project uses in the Gemfile.
* Don't use `unless`.
* Prefer classes to modules when designing functionality that is shared by
multiple models.
* Prefer `detect` over `find` and `select` over `find_all` to avoid confusion
with ActiveRecord and keep `select`/`reject` symmetry.
* Prefer `map` over `collect` and `reduce` over `inject` due to symmetry and
familarity with mapping and reducing in other technologies.
* Use `%{}` for single-line strings needing interpolation and double-quotes.
* Use `%w()` over `['', '']` for an array of words.
* Use `&&` and `||` for boolean expressions.
* Use `||=` freely.
* Use `{...}` over `do..end` for single-line blocks.
* Use `!` suffix for dangerous methods (modifies `self`).
* Use `?` suffix for predicate methods (return a boolean).
* Use `CamelCase` for classes and modules, `snake_case` for variables and
methods, `SCREAMING_SNAKE_CASE` for constants.
* Use `def` with parentheses when there are arguments.
* Use `do..end` over `{...}` for multi-line blocks.
* Use `each`, not `for`, for iteration.
* Use heredocs for multi-line strings.
* Use `/(?:first|second)/` over `/(first|second)/` when you don't need the
captured group.
* Use `private` over `protected` to indicate scope.
* Use `def self.method` over `def Class.method` or `class << self`.
* Use `Set` over `Array` for arrays with unique elements. The lookup is faster.
* Use single-quotes for strings unless interpolating.
* Use `unless boolean?` instead of `if !boolean?`.
* Use [Factory Girl](https://github.com/thoughtbot/factory_girl) for setting up
complicated test data.