From e4117d814059524ffeccc31472a92c8c44a8b7d3 Mon Sep 17 00:00:00 2001 From: heyvaleria Date: Fri, 4 Apr 2025 11:21:05 +0200 Subject: [PATCH 1/2] wip --- ruby/README.md | 30 +++++++----- ruby/how-to.md | 127 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 13 deletions(-) create mode 100644 ruby/how-to.md diff --git a/ruby/README.md b/ruby/README.md index 4c2d87eb..a684846a 100644 --- a/ruby/README.md +++ b/ruby/README.md @@ -1,14 +1,22 @@ # 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) + + + + +- 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 @@ -30,10 +38,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 @@ -42,9 +49,6 @@ 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 diff --git a/ruby/how-to.md b/ruby/how-to.md new file mode 100644 index 00000000..95ff0195 --- /dev/null +++ b/ruby/how-to.md @@ -0,0 +1,127 @@ +# 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 +``` + + + + + + +* Avoid `%q`, `%Q`, `%x`, `%s`, and `%W`. +* Avoid hashes as optional parameters. Does the method do too much? +* Avoid including code and gems in source control that are specific to your + development machine or process. Examples: `.rvmrc`, file watchers, debuggers. +* Avoid meta-programming. +* Avoid monkey-patching core classes. +* Avoid `return` unless required. +* 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 unused block parameters. + hash.map { |_, v| v + 1 } +* 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. From 68b8032ad8ee5320e8dd528fd3d6aeca04ef334b Mon Sep 17 00:00:00 2001 From: heyvaleria Date: Mon, 7 Apr 2025 16:45:58 +0200 Subject: [PATCH 2/2] wip --- ruby/README.md | 8 ++++---- ruby/how-to.md | 24 ++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/ruby/README.md b/ruby/README.md index a684846a..a0d5767b 100644 --- a/ruby/README.md +++ b/ruby/README.md @@ -11,9 +11,11 @@ - [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. @@ -27,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] @@ -54,7 +55,6 @@ [#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 diff --git a/ruby/how-to.md b/ruby/how-to.md index 95ff0195..f9d15224 100644 --- a/ruby/how-to.md +++ b/ruby/how-to.md @@ -64,6 +64,7 @@ Avoid ternary operators. Use multi-line `if` instead to emphasize code branches. ## [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. @@ -75,10 +76,31 @@ modify the user, raise an exception, or do something else. def send_invitation_email ``` +## [Unused block parameters](#unused-block-params) + +```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) +``` +--- * Avoid `%q`, `%Q`, `%x`, `%s`, and `%W`. * Avoid hashes as optional parameters. Does the method do too much? @@ -101,8 +123,6 @@ modify the user, raise an exception, or do something else. 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 unused block parameters. - hash.map { |_, v| v + 1 } * Use `%{}` for single-line strings needing interpolation and double-quotes. * Use `%w()` over `['', '']` for an array of words. * Use `&&` and `||` for boolean expressions.