├── README.md ├── lib └── rubocop-rails-omakase.rb ├── rubocop-rails-omakase.gemspec └── rubocop.yml /README.md: -------------------------------------------------------------------------------- 1 | # Omakase Ruby styling for Rails 2 | 3 | Ruby is a beautifully expressive language that not only tolerates many different dialects, but celebrates their diversity. It was never meant as a language to be written exclusively in a single style across all libraries, frameworks, or applications. If you or your team has developed a particular house style that brings you joy, you should cherish that. 4 | 5 | This collection of RuboCop styles is for those who haven't committed to any specific dialect already. Who would just like to have a reasonable starting point, and who will benefit from some default rules to at least start a consistent approach to Ruby styling. 6 | 7 | These specific rules aren't right or wrong, but merely represent the idiosyncratic aesthetic sensibilities of Rails' creator. Use them whole, use them as a starting point, use them as inspiration, or however you see fit. 8 | 9 | ## Installation 10 | 11 | New Rails applications (Rails 7.2+) automatically include this omakase style. No installation is necessary. 12 | 13 | For apps generated with older versions of Rails, you can add it yourself. 14 | 15 | First add this to your Gemfile: 16 | 17 | ```ruby 18 | gem "rubocop-rails-omakase", require: false, group: [ :development ] 19 | ``` 20 | 21 | Then run `bundle`, then `bundle binstubs rubocop`. 22 | 23 | Then add a default `.rubocop.yml` file in the root of your application with: 24 | 25 | ```yml 26 | # Omakase Ruby styling for Rails 27 | inherit_gem: 28 | rubocop-rails-omakase: rubocop.yml 29 | 30 | # Your own specialized rules go here 31 | ``` 32 | 33 | Now you can run `./bin/rubocop` to check for compliance and `./bin/rubocop -a` to automatically fix violations. 34 | 35 | 36 | ## Contributing 37 | 38 | These omakase styles are not intended as an invitation to bikeshed code style preferences. If you disagree with some of the rules incorporated here, you should specialize them in your own application. If you disagree with most of the rules, you should just create your own style guide from scratch. 39 | 40 | The only type of contributions that will be considered is those pertaining to bugs or obvious inconsistencies that remain in the spirit of the omakase collection. 41 | 42 | 43 | ## License 44 | 45 | This gem is released under the [MIT License](https://opensource.org/license/mit/). 46 | -------------------------------------------------------------------------------- /lib/rubocop-rails-omakase.rb: -------------------------------------------------------------------------------- 1 | # Stub so Bundler can quietly require the gem. 2 | -------------------------------------------------------------------------------- /rubocop-rails-omakase.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = "rubocop-rails-omakase" 3 | s.summary = "Omakase Ruby styling for Rails" 4 | s.author = "David Heinemeier Hansson" 5 | s.email = "david@hey.com" 6 | s.homepage = "https://github.com/rails/rubocop-rails-omakase" 7 | 8 | s.license = "MIT" 9 | 10 | s.version = "1.1.0" 11 | s.platform = Gem::Platform::RUBY 12 | 13 | s.add_dependency "rubocop", ">= 1.74" 14 | s.add_dependency "rubocop-rails", ">= 2.30" 15 | s.add_dependency "rubocop-performance", ">= 1.24" 16 | 17 | s.files = %w[ rubocop.yml ] 18 | end 19 | -------------------------------------------------------------------------------- /rubocop.yml: -------------------------------------------------------------------------------- 1 | plugins: 2 | - rubocop-performance 3 | - rubocop-rails 4 | 5 | inherit_mode: 6 | merge: 7 | - Exclude 8 | 9 | AllCops: 10 | SuggestExtensions: false 11 | Exclude: 12 | - "data/**/*" 13 | 14 | # All cops except your using extensions are disabled by default. 15 | Bundler: 16 | Enabled: false 17 | Gemspec: 18 | Enabled: false 19 | Layout: 20 | Enabled: false 21 | Lint: 22 | Enabled: false 23 | Metrics: 24 | Enabled: false 25 | Naming: 26 | Enabled: false 27 | Performance: 28 | Enabled: false 29 | Exclude: 30 | - "test/**/*" 31 | Rails: 32 | Enabled: false 33 | Security: 34 | Enabled: false 35 | Style: 36 | Enabled: false 37 | 38 | # Align `when` with `end`. 39 | Layout/CaseIndentation: 40 | Enabled: true 41 | EnforcedStyle: end 42 | 43 | # Align comments with method definitions. 44 | Layout/CommentIndentation: 45 | Enabled: true 46 | 47 | Layout/ElseAlignment: 48 | Enabled: true 49 | 50 | Layout/EmptyLineAfterMagicComment: 51 | Enabled: true 52 | 53 | Layout/EmptyLinesAroundBlockBody: 54 | Enabled: true 55 | 56 | # In a regular class definition, no empty lines around the body. 57 | Layout/EmptyLinesAroundClassBody: 58 | Enabled: true 59 | 60 | # In a regular method definition, no empty lines around the body. 61 | Layout/EmptyLinesAroundMethodBody: 62 | Enabled: true 63 | 64 | # In a regular module definition, no empty lines around the body. 65 | Layout/EmptyLinesAroundModuleBody: 66 | Enabled: true 67 | 68 | # Align `end` with the matching keyword or starting expression except for 69 | # assignments, where it should be aligned with the LHS. 70 | Layout/EndAlignment: 71 | Enabled: true 72 | EnforcedStyleAlignWith: variable 73 | 74 | # Method definitions after `private` or `protected` isolated calls need one 75 | # extra level of indentation. 76 | # 77 | # We break this rule in context, though, e.g. for private-only concerns, 78 | # so we leave it disabled. 79 | Layout/IndentationConsistency: 80 | Enabled: false 81 | EnforcedStyle: indented_internal_methods 82 | 83 | # Detect hard tabs, no hard tabs. 84 | Layout/IndentationStyle: 85 | Enabled: true 86 | 87 | # Two spaces, no tabs (for indentation). 88 | # 89 | # Doesn't behave properly with private-only concerns, so it's disabled. 90 | Layout/IndentationWidth: 91 | Enabled: false 92 | 93 | Layout/LeadingCommentSpace: 94 | Enabled: true 95 | 96 | Layout/SpaceAfterColon: 97 | Enabled: true 98 | 99 | Layout/SpaceAfterComma: 100 | Enabled: true 101 | 102 | Layout/SpaceAroundEqualsInParameterDefault: 103 | Enabled: true 104 | 105 | Layout/SpaceAroundKeyword: 106 | Enabled: true 107 | 108 | # Use `foo {}` not `foo{}`. 109 | Layout/SpaceBeforeBlockBraces: 110 | Enabled: true 111 | 112 | Layout/SpaceBeforeComma: 113 | Enabled: true 114 | 115 | Layout/SpaceBeforeFirstArg: 116 | Enabled: true 117 | 118 | # Use `->(x, y) { x + y }` not `-> (x, y) { x + y }` 119 | Layout/SpaceInLambdaLiteral: 120 | Enabled: true 121 | 122 | # Use `[ a, [ b, c ] ]` not `[a, [b, c]]` 123 | # Use `[]` not `[ ]` 124 | Layout/SpaceInsideArrayLiteralBrackets: 125 | Enabled: true 126 | EnforcedStyle: space 127 | EnforcedStyleForEmptyBrackets: no_space 128 | 129 | # Use `%w[ a b ]` not `%w[ a b ]`. 130 | Layout/SpaceInsideArrayPercentLiteral: 131 | Enabled: true 132 | 133 | # Use `foo { bar }` not `foo {bar}`. 134 | # Use `foo { }` not `foo {}`. 135 | Layout/SpaceInsideBlockBraces: 136 | Enabled: true 137 | EnforcedStyleForEmptyBraces: space 138 | 139 | # Use `{ a: 1 }` not `{a:1}`. 140 | # Use `{}` not `{ }`. 141 | Layout/SpaceInsideHashLiteralBraces: 142 | Enabled: true 143 | EnforcedStyle: space 144 | EnforcedStyleForEmptyBraces: no_space 145 | 146 | # Use `foo(bar)` not `foo( bar )` 147 | Layout/SpaceInsideParens: 148 | Enabled: true 149 | 150 | # Requiring a space is not yet supported as of 0.59.2 151 | # Use `%w[ foo ]` not `%w[foo]` 152 | Layout/SpaceInsidePercentLiteralDelimiters: 153 | Enabled: false 154 | #EnforcedStyle: space 155 | 156 | # Use `hash[:key]` not `hash[ :key ]` 157 | Layout/SpaceInsideReferenceBrackets: 158 | Enabled: true 159 | 160 | # Blank lines should not have any spaces. 161 | Layout/TrailingEmptyLines: 162 | Enabled: true 163 | 164 | # No trailing whitespace. 165 | Layout/TrailingWhitespace: 166 | Enabled: true 167 | 168 | Lint/RedundantStringCoercion: 169 | Enabled: true 170 | 171 | # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg. 172 | Lint/RequireParentheses: 173 | Enabled: true 174 | 175 | Lint/UriEscapeUnescape: 176 | Enabled: true 177 | 178 | Performance/FlatMap: 179 | Enabled: true 180 | 181 | # Prefer assert_not over assert ! 182 | Rails/AssertNot: 183 | Include: 184 | - "test/**/*" 185 | 186 | # Prefer assert_not_x over refute_x 187 | Rails/RefuteMethods: 188 | Include: 189 | - "test/**/*" 190 | 191 | # We generally prefer &&/|| but like low-precedence and/or in context 192 | Style/AndOr: 193 | Enabled: false 194 | 195 | # Prefer Foo.method over Foo::method 196 | Style/ColonMethodCall: 197 | Enabled: true 198 | 199 | Style/DefWithParentheses: 200 | Enabled: true 201 | 202 | # Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }. 203 | Style/HashSyntax: 204 | Enabled: true 205 | EnforcedShorthandSyntax: either 206 | 207 | # Defining a method with parameters needs parentheses. 208 | Style/MethodDefParentheses: 209 | Enabled: true 210 | 211 | Style/ParenthesesAroundCondition: 212 | Enabled: true 213 | 214 | Style/PercentLiteralDelimiters: 215 | Enabled: true 216 | PreferredDelimiters: 217 | default: "()" 218 | "%i": "[]" 219 | "%I": "[]" 220 | "%r": "{}" 221 | "%w": "[]" 222 | "%W": "[]" 223 | 224 | # Use quotes for string literals when they are enough. 225 | Style/RedundantPercentQ: 226 | Enabled: false 227 | 228 | Style/RedundantReturn: 229 | Enabled: true 230 | AllowMultipleReturnValues: true 231 | 232 | Style/Semicolon: 233 | Enabled: true 234 | AllowAsExpressionSeparator: true 235 | 236 | Style/StabbyLambdaParentheses: 237 | Enabled: true 238 | 239 | # Use `"foo"` not `'foo'` unless escaping is required 240 | Style/StringLiterals: 241 | Enabled: true 242 | EnforcedStyle: double_quotes 243 | Include: 244 | - "app/**/*" 245 | - "config/**/*" 246 | - "lib/**/*" 247 | - "test/**/*" 248 | - "Gemfile" 249 | 250 | Style/TrailingCommaInArrayLiteral: 251 | Enabled: true 252 | 253 | Style/TrailingCommaInHashLiteral: 254 | Enabled: true 255 | --------------------------------------------------------------------------------