Last active
August 29, 2015 14:24
-
-
Save alloy-d/8bf9a6a3d7ad142152b3 to your computer and use it in GitHub Desktop.
Overture house style guide.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# # Overture's House Style Guide for Ruby | |
# | |
# This is a configuration file for [Rubocop][rubocop]. | |
# | |
# It is based on [the default configuration file for Rubocop | |
# 0.32.1][rubocop-source-default-config]. | |
# | |
# This style guide assumes that you are not writing code for any version | |
# of Ruby before version 1.9. | |
# | |
# [rubocop]: https://github.com/bbatsov/rubocop | |
# [rubocop-source-default-config]: https://github.com/bbatsov/rubocop/blob/v0.32.1/config/default.yml | |
# ## Usage | |
# | |
# Put this file in the root of your project as `.rubocop.yml`. | |
# Expectation: we will have some minimal project-specific configuration. | |
# Put that in `.rubocop-project.yml`. | |
#inherit_from: | |
# - .rubocop-project.yml | |
AllCops: | |
DisplayCopNames: yes | |
DisplayStyleGuide: yes | |
# --- | |
# The best compromise for readability is the "table" style enforced by | |
# Rubocop. It keeps keys, values, and hash rockets (if applicable) | |
# left-aligned in columns. | |
# | |
# To illustrate: | |
# | |
# example = { | |
# "key one" => 1 | |
# "second" => 2 | |
# "x" => "3" | |
# } | |
# | |
# These rules are applied to a hash passed in as the last argument to | |
# a method call only if it is *explicit* (i.e., it has the braces). | |
# | |
# Implicit hashes are meant for compactness or clarity, and enforcing | |
# alignment rules could conflict with those goals. | |
Style/AlignHash: | |
EnforcedHashRocketStyle: table | |
EnforcedColonStyle: table | |
EnforcedLastArgumentHashStyle: ignore_implicit | |
# --- | |
# When a method call is split across lines, we prefer the arguments | |
# indented for consistency with the rest of the code, instead of aligned | |
# with the call's parentheses. | |
# | |
# For example: | |
# | |
# good_method_call( | |
# "this is the first argument.", | |
# "this is argument number two!", | |
# ) | |
# | |
# is more readable than | |
# | |
# bad_method_call("this is the first argument.", | |
# "this is argument number two!") | |
# | |
# The second breaks the flow of the code's indentation and makes it | |
# harder for the eye to parse. It also makes it far more likely that | |
# argument lines will wrap and become unwieldy. | |
# | |
# ### Unenforced Rules | |
# | |
# Additional style preferences that Rubocop does not enforce: | |
# | |
# - If a method call is split across lines, each argument should be on | |
# its own line, *including the first argument*. | |
# - If a method call is split across lines, each argument should have | |
# a trailing comma, *including the last argument*. | |
# - If a method call is split across lines, the closing parenthesis | |
# should be on a line of its own, with the same indentation as the | |
# start of the method call. | |
# | |
Style/AlignParameters: | |
EnforcedStyle: with_fixed_indentation | |
# --- | |
# `and` and `or` do not have the same precedence as `&&` and `||`, so | |
# their use in conditionals is confusing. We prefer consistent use of | |
# `&&` and `||` for clarity. | |
# | |
# `and` and `or` do have some clear uses for control flow, so we'll | |
# allow that: | |
# | |
# File.exist?(".rubocop.yml") or raise "YOU ARE DREADFULLY UNSTYLISH" | |
# | |
# ### Unenforced Rules | |
# | |
# An additional rule that is *not* enforced by Rubocop is that `!` | |
# should also be preferred to `not`. `not` has issues similar to those | |
# of `and` and `or`. It also (fun fact!) inexplicably causes syntax | |
# errors in some combinations with them. | |
Style/AndOr: | |
EnforcedStyle: conditionals | |
# --- | |
# The block delimiters cop will enforce braces or `do`/`end` around | |
# blocks depending on either length (braces for single-line blocks) or | |
# context (braces for functional blocks). | |
# | |
# Our style can't be fully enforced by either of those rules, so this | |
# cop is disabled. | |
# | |
# ### Unenforced Rules | |
# | |
# Our style is this: | |
# | |
# - `do`/`end` should *always* be used for multi-line blocks. A block | |
# braces should never span more than one line. | |
# - `do`/`end` can be used around a single-line block when the line is | |
# long or putting it in a `do`/`end` block adds clarity. | |
# | |
# For example: | |
# | |
# style_guide.tap {|s| s.save! } | |
# | |
# new_guide = style_guide.rules.map do |rule| | |
# rule.explanation.gsub("Ruby", "Elixir") | |
# end | |
# | |
# are probably more readable than | |
# | |
# style_guide.tap do |guide| | |
# guide.save! | |
# end | |
# | |
# new_guide = style_guide.rules.map{|r| r.explanation.gsub("Ruby", "Elixir") } | |
# | |
Style/BlockDelimiters: | |
Enabled: false | |
# --- | |
# This cop enforces a preference on braces around hash literals in | |
# parameters. Its provided policies don't match our style. | |
# | |
# ### Unenforced Rules | |
# | |
# - Braces must be used when there is more than one hash parameter. | |
# Otherwise, Ruby will not be able to divide the hash parameters | |
# correctly. | |
# - Braces should be used when a hash parameter is split across lines. | |
# In that case, the first entry in the hash should be on a new line | |
# after the opening brace. | |
# - Braces should generally not be used for an implicit hash as the | |
# parameter, but this is up to the author's discretion. | |
# | |
# For example: | |
# | |
# good_method_call({first_hash: true}, {second_hash: true}) | |
# | |
# good_method_call({ | |
# first_option: "one", | |
# second_option: 2, | |
# }) | |
# | |
# good_method_call(implicit_hash: true) | |
# | |
Style/BracesAroundHashParameters: | |
Enabled: false | |
# --- | |
# There is no aesthetically pleasing way to indent a `case` block. | |
# | |
# The `end` corresponding to a `case` should start on the same column as | |
# the line that started the `case`. | |
Style/CaseIndentation: | |
IndentWhenRelativeTo: end | |
IndentOneStep: yes | |
# --- | |
# Whether to use the nested or compact style for class or module | |
# definitions is up to the author's discretion. | |
# | |
# The nested style is usually preferable, but it can become unwieldy if | |
# the nesting hierarchy is complex. | |
# | |
# A good rule of thumb is probably to use the nested style unless you're | |
# nesting something more than 2 or 3 levels deep. | |
Style/ClassAndModuleChildren: | |
Enabled: false | |
# --- | |
# Both `kind_of?` and `is_a?` are available methods for checking | |
# class and module inheritance. | |
# | |
# Each has cases in which it is more clear. It's up to the author's | |
# discretion as long as clarity is achieved. | |
Style/ClassCheck: | |
Enabled: false | |
# --- | |
# `map`, `reduce`, `find`, and `select` are clear and common names. | |
# `collect`, `inject`, and `detect` are not less-obvious aliases for | |
# these, and are not preferred. | |
Style/CollectionMethods: | |
PreferredMethods: | |
collect: 'map' | |
collect!: 'map!' | |
inject: 'reduce' | |
detect: 'find' | |
find_all: 'select' | |
# --- | |
# Backticks are clear and easy to understand for single-line shell | |
# commands. | |
# | |
# If you need to split a shell command across multiple lines, use `%x`. | |
Style/CommandLiteral: | |
EnforcedStyle: mixed | |
# --- | |
# There are a few types of "special" comments like `# TODO` | |
# that should follow a standard format. | |
# | |
# Rubocop will ensure that any comment that starts with one of the | |
# keywords below has a colon and a comment: | |
# | |
# # REVIEW: we probably don't need all of these keywords, though. | |
# | |
Style/CommentAnnotation: | |
Keywords: | |
- TODO | |
- FIXME | |
- OPTIMIZE | |
- HACK | |
- REVIEW | |
# --- | |
# It's easier to see at a glance that method chaining is happening | |
# if the dot is at the beginning of the line. | |
# | |
# Putting the dot at the beginning of the line also makes it easier to | |
# add extra methods into a chain. It also makes VCS history cleaner; | |
# see the argument for `Style/TrailingComma` for a similar argument. | |
# | |
# We prefer | |
# | |
# (1..10).map {|n| n * 2 } | |
# .take {|n| n % 5 == 3 } | |
# .each {|n| puts n } | |
# | |
# to | |
# | |
# (1..10).map {|n| n * 2 }. | |
# take {|n| n % 5 == 3 }. | |
# each {|n| puts n } | |
# | |
Style/DotPosition: | |
EnforcedStyle: leading | |
# --- | |
# An empty else is redundant and unnecessary, | |
# but an else with a nil make intent explicit. | |
# | |
# Have an `else` block that evaluates to `nil` if you think it makes | |
# your code more clear. | |
Style/EmptyElse: | |
EnforcedStyle: empty | |
# --- | |
# Empty lines break up code. | |
# | |
# We will not stop you from having two empty lines in a row, | |
# if you feel that it makes your code clearer or cleaner. | |
Style/EmptyLines: | |
Enabled: false | |
# --- | |
# Keeping empty lines around access modifiers makes them more prominent. | |
# | |
# Access modifiers don't change indentation, so they run the risk of looking | |
# like they're associated with the following method if they're placed too | |
# close. The empty line adds clarity. | |
Style/EmptyLinesAroundAccessModifier: | |
Enabled: true | |
# --- | |
# One-line defs should be concise and obvious. | |
# | |
# Empty lines between them shouldn't be too helpful, | |
# so feel free to butt them up against each other if you think it's | |
# clear. | |
Style/EmptyLineBetweenDefs: | |
AllowAdjacentOneLineDefs: true | |
# --- | |
# It looks ridiculous to require an empty line at the beginning of every | |
# block, but it *can* aid clarity in some cases if an empty line is | |
# included. | |
# | |
# You should generally not include an empty line, but you should do so | |
# at your discretion if it enhances clarity for the reader. | |
Style/EmptyLinesAroundBlockBody: | |
Enabled: false | |
Style/EmptyLinesAroundClassBody: | |
Enabled: false | |
Style/EmptyLinesAroundModuleBody: | |
Enabled: false | |
# --- | |
# The encoding for a file controls what the interpreter expects to see. | |
# | |
# It *also* affects how strings are treated *in the context of that | |
# file*, so | |
# | |
# - it should always be specified explicitly. | |
# - it should be specified consistently across the codebase. | |
# - it should be set to utf-8 unless there is a *very, very good | |
# reason* to do something else. | |
# | |
Style/Encoding: | |
EnforcedStyle: always | |
AutoCorrectEncodingComment: '# encoding: utf-8' | |
Style/FirstParameterIndentation: | |
EnforcedStyle: consistent | |
# --- | |
# A `for` can either be done as an `each` or, in rarer cases, a `while`. | |
# | |
# We prefer `each`, because it is more idiomatic Ruby and is probably | |
# always cleaner. | |
Style/For: | |
EnforcedStyle: each | |
# --- | |
# Ruby's `sprintf` works exactly the same as `sprintf` anywhere else | |
# (like, say, in C). That makes it clear to anyone who has ever seen | |
# a `sprintf` before. | |
# | |
# `format`, while a more sensible name, is less common and can mean | |
# different things in other languages. | |
# | |
# We prefer `sprintf` for clarity. | |
Style/FormatString: | |
EnforcedStyle: sprintf | |
# --- | |
# ### Unenforced Rules | |
# | |
# Guard clauses can be simpler and clearer than full-blown conditionals | |
# in many cases. We prefer them in those cases: | |
# | |
# def process | |
# do_process if ready_to_process? | |
# end | |
# | |
# get '/protected' do | |
# return 401 if !current_user.authorized? | |
# | |
# # continue for authorized users only | |
# end | |
# | |
# However, there are cases in which an explicit conditional makes the | |
# author's intent more clear. Using conditionals in those cases is up | |
# to the author's discretion. | |
# | |
# Especially in cases where we halt processing based on a condition (for | |
# example, the `return 401 if !current_user.authorized?` above), we | |
# prefer the guard clause, since it puts the `return` (or `next` or | |
# other flow-halting thing) prominently at the front of the line. | |
Style/GuardClause: | |
Enabled: false | |
# --- | |
# When writing a hash literal: | |
# | |
# - use Ruby 1.9 syntax if your keys are only symbols. | |
# - use hash rockets for *all* keys if they are not *all* symbols. | |
# | |
Style/HashSyntax: | |
EnforcedStyle: ruby19_no_mixed_keys | |
# Gemfiles, however, have their own standard syntax. | |
# Let's not police that. | |
Exclude: | |
- Gemfile | |
# --- | |
# A multiline if/unless is more blatantly clear than a modifier. | |
# | |
# If you think it adds necessary clarity to your code, use a multiline | |
# if/unless. | |
Style/IfUnlessModifier: | |
Enabled: false | |
# --- | |
# Indentation should always be consistent, with two-space indentation | |
# levels. | |
# | |
# Method definitions should always be indented one level from the | |
# enclosing scope, even if they are modified by a `protected` or | |
# `private` modifier. Those access modifiers do not have | |
# a corresponding `end`, so they should not change the indentation | |
# level. | |
# | |
# class Thingy | |
# def do_things | |
# # ... | |
# end | |
# | |
# private | |
# def do_private_things | |
# # ... | |
# end | |
# end | |
# | |
# If the first key of a hash is on a separate line from the opening | |
# brace, it should be indented on level from the start of the line | |
# containing the opening brace. For example: | |
# | |
# # Yes! | |
# pretty_method_call({ | |
# first_key: "indented one level", | |
# }) | |
# | |
# # Yuck! | |
# hideous_method_call({ | |
# first_key: "way out in the margins!", | |
# }) | |
# | |
Style/IndentationConsistency: | |
EnforcedStyle: normal | |
Style/IndentationWidth: | |
Width: 2 | |
Style/IndentHash: | |
EnforcedStyle: consistent | |
# --- | |
# ### Unenforced Rules | |
# | |
# We prefer the new 1.9-style lambda shorthand for consistency. | |
# | |
# Use the old style `lambda do ... end` when it stands alone and | |
# makes the code more clear, but feel free to use the new style | |
# wherever it makes the code more consistent. | |
# | |
# Always use the new style for single-line lambdas. | |
# | |
# # Good: | |
# id = ->(x) { x } | |
# palindrome = ->(x) do | |
# reversed = x.reverse | |
# x + reversed | |
# end | |
Style/Lambda: | |
Enabled: false | |
# --- | |
# ### Unenforced Rules | |
# | |
# There are three ways to call `Proc`s. | |
# | |
# We support either using `.call()` or `[]`; there are good use cases | |
# for each, and which to use is up to your discretion. A good rule of | |
# thumb is that you should use `[]` when it contextually resembles | |
# a hash or array access and makes the code more readable. | |
# | |
# You should not use `.()`, because it resembles literally nothing else | |
# in Ruby and makes no sense to new readers. | |
# | |
# To clarify: | |
# | |
# id = ->(x) { x } | |
# | |
# id.call(5) # => good! | |
# id[5] # => good (sometimes). | |
# id.(5) # => WTF even is this? | |
# | |
# This cop allows enforcing either `[]` or `.call()`, but not allowing | |
# both. | |
Style/LambdaCall: | |
Enabled: false | |
# --- | |
# ### Unenforced Rules | |
# | |
# You should always have a space before textual comments. | |
# | |
# It sometimes enhances clarity to have no space before commented-out code. | |
# | |
# However, you should not routinely check in commented-out code. | |
# If you intend to delete it, then make sure it is in VCS history and just delete it. | |
Style/LeadingCommentSpace: | |
Enabled: false | |
# --- | |
# This enforces using `unless whatever` instead of `if !whatever`. | |
# | |
# The choice of `unless` versus `if not` is a choice made by the author to | |
# show intent, so we won't enforce either. Write what is most clear. | |
Style/NegatedIf: | |
Enabled: false | |
# --- | |
# This enforces using `next` to skip iteration instead of ending an | |
# iteration block with a conditional. | |
# | |
# The example from [Rubocop's source][rubocop-source-style-next] | |
# follows: | |
# | |
# # Bad: | |
# [1, 2].each do |a| | |
# if a == 1 | |
# puts a | |
# end | |
# end | |
# | |
# # Good: | |
# [1, 2].each do |a| | |
# next unless a == 1 | |
# puts a | |
# end | |
# | |
# [rubocop-source-style-next]: https://github.com/bbatsov/rubocop/blob/v0.32.1/lib/rubocop/cop/style/next.rb | |
# | |
Style/Next: | |
EnforcedStyle: skip_modifier_ifs | |
MinBodyLength: 3 | |
# --- | |
# `if !x.nil?` is more explicit and clear than `if x`. | |
# | |
# Either is acceptable, and it's up to the author's discretion whether | |
# `if x` is clear enough. | |
# | |
# When in doubt, use `.nil?`. | |
Style/NonNilCheck: | |
IncludeSemanticChanges: false | |
# --- | |
# We prefer method definitions to have parenthesis around parameters, | |
# simply because it's less jarring: | |
# | |
# # Consistent and clear: | |
# def take_arguments(one, another) end | |
# | |
# # Jarring: | |
# def take_arguments one, another end | |
# | |
Style/MethodDefParentheses: | |
EnforcedStyle: require_parentheses | |
# --- | |
# Snake-case method names are consistent with core Ruby and the standard | |
# library. | |
Style/MethodName: | |
EnforcedStyle: snake_case | |
# --- | |
# Chaining multiline blocks can be ugly, but it can be useful for expressing | |
# a functional pipeline that data passes through. | |
# | |
# If you're using a lot of multiline blocks, consider whether they can be | |
# turned into methods instead. | |
Style/MultilineBlockChain: | |
Enabled: false | |
# --- | |
# Indentation makes it visually clear that something is happening | |
# across lines. | |
Style/MultilineOperationIndentation: | |
EnforcedStyle: indented | |
# --- | |
# Once your numeric literals get sufficiently large, you should aid the | |
# reader by using `_` to separate each three digits. | |
# | |
# You should do this once you get to six digits: | |
# | |
# 600_000 # => yay, I can read it! | |
# 600000 # => my god, it's full of zeroes. | |
# | |
Style/NumericLiterals: | |
MinDigits: 6 | |
# Compelling use case for safe assignment in conditions: | |
# | |
# author = "Adam Lloyd <[email protected]>" | |
# | |
# if (m = author.match(/(#{EMAIL_REGEX})/)) | |
# send_angry_email(m[1]) | |
# end | |
# | |
Style/ParenthesesAroundCondition: | |
AllowSafeAssignment: true | |
# --- | |
# You can use whatever gobbledygook delimiters you want when using | |
# percent literals. Sometimes that's good, but it's probably better to | |
# be consistent. | |
# | |
# Brackets are convenient because they are paired and therefore don't | |
# need to be escaped within the literal as long as they remain paired. | |
# | |
# For all except regexes (`%r`), parentheses make sense. For regexes, | |
# all of the bracket pairs have meaning, so we'll use `{}`, as it's less | |
# common than `()` and `[]`. | |
# | |
# These are the Rubocop defaults. | |
Style/PercentLiteralDelimiters: | |
PreferredDelimiters: | |
'%': () | |
'%i': () | |
'%q': () | |
'%Q': () | |
'%r': '{}' | |
'%s': () | |
'%w': () | |
'%W': () | |
'%x': () | |
# --- | |
# We provide multiple arguments to `raise`, instead of using | |
# `Exception.new`: | |
# | |
# # Good! | |
# raise StyleException, "you are exceptionally stylish" | |
# | |
# # Nope. | |
# raise StyleException.new("your exceptions ain't on fleek") | |
# | |
# Confession: this is entirely because I always forget the `.new` and | |
# try to call the Exception subclass as a method. | |
Style/RaiseArgs: | |
EnforcedStyle: exploded | |
# --- | |
# Passing multiple arguments to `return` results in returning an array. | |
# | |
# You should just be clear and make the array explicit. | |
Style/RedundantReturn: | |
AllowMultipleReturnValues: false | |
# --- | |
# In many cases, explicitly making calls against `self` is safer and more clear. | |
# | |
# We encourage using `self`, even if it's redundant. | |
Style/RedundantSelf: | |
Enabled: false | |
# --- | |
# The choices here are: | |
# - slashes, which enforces slashes always | |
# - percent_r, which enforces %r always | |
# - mixed, which enforces slashes for single-line and %r for | |
# multi-line. | |
# | |
# Our ideal situation would be: | |
# - slashes always, | |
# - unless there's a slash in the regex, for which %r is better, | |
# - and with the `x` modifier on multi-line regexes. | |
# | |
# The `x` modifier lets you break regexes across lines and put | |
# comments in them, which seems like a *really* good idea if you have | |
# a regex that is so large that you want to break it across lines. | |
# | |
# This is a fairly good approximation of that, minus the `x` bit. | |
Style/RegexpLiteral: | |
EnforcedStyle: slashes | |
AllowInnerSlashes: false | |
# --- | |
# The rescue modifier is bad practice for doing real error handling, | |
# but can be used effectively. | |
# | |
# If you have a need to handle a particular class of error, use a | |
# multiline `begin`/`rescue`. If you need to make sure that, e.g., | |
# a value exists regardless of *any* error that occurs in fetching it, | |
# a rescue modifier is fine. | |
Style/RescueModifier: | |
Enabled: false | |
# --- | |
# Assuming the use of "expression" is on point here, this should allow | |
# | |
# def shorty; true end | |
# | |
# but not | |
# | |
# def shorty; puts 'lol j/k long'; true end | |
# | |
# This will almost always result in more readable code. | |
Style/Semicolon: | |
AllowAsExpressionSeparator: false | |
# --- | |
# `fail` is a synonym for `raise`, but it's unusual and is apparently | |
# overridden in some places. | |
# | |
# We prefer `raise`, which is the clear standard. | |
# | |
# See: https://github.com/bbatsov/ruby-style-guide/issues/233 | |
Style/SignalException: | |
EnforcedStyle: only_raise | |
# --- | |
# Block param names can be a form of documentation for the block. | |
# | |
# Rubocop can enforce specific variables names for one-line blocks, | |
# but we would prefer to leave them up to the author's discretion. | |
Style/SingleLineBlockParams: | |
Enabled: false | |
# --- | |
# I think single-line methods can be very clear if they're short, | |
# and I think there's some space between "short" and "empty", which is | |
# the only thing this cop supports. | |
# | |
# Single-line methods are bad if they're complex, but something like | |
# | |
# def supports_editing?; true end | |
# | |
# is plenty clear and concise, despite not being totally empty. | |
Style/SingleLineMethods: | |
Enabled: false | |
# --- | |
# It's probably better to go with single quotes in general. | |
# | |
# However, that becomes tricky when you have apostrophes or single | |
# quotes in the string you're quoting, and I think it looks bad to | |
# single-quote any string except those that have single quotes in | |
# them. | |
# | |
# Also, single-quoting by means that you need to change your quote | |
# style if you want to use interpolation. Doing that by default sets | |
# you up to accidentally try interpolation in non-interpolated | |
# strings. | |
Style/StringLiterals: | |
EnforcedStyle: double_quotes | |
# --- | |
# Here, it probably makes sense to enforce single-quotes. | |
# | |
# It's less potentially misleading on first glance, and it discourages | |
# doing interpolation inside of interpolation. If you're thinking of | |
# doing that, it's probably a bad and super-confusing idea. | |
Style/StringLiteralsInInterpolation: | |
EnforcedStyle: single_quotes | |
# --- | |
# Preference: | |
# | |
# lambda {|x| x } | |
# | |
# looks better and easier for the eye to parse than | |
# | |
# lambda {| x | x } | |
# | |
Style/SpaceAroundBlockParameters: | |
EnforcedStyleInsidePipes: no_space | |
# --- | |
# Preference: | |
# | |
# def something(required, defaulted="defaulted") | |
# | |
# is easier for the eye to parse clearly than | |
# | |
# def something(required, defaulted = "defaulted") | |
# | |
Style/SpaceAroundEqualsInParameterDefault: | |
EnforcedStyle: no_space | |
# --- | |
# Allowing multiple spaces around `=` and `=>` allows authors to align | |
# contiguous lines neatly. | |
# | |
# Think | |
# | |
# short = true | |
# super_long_name = true | |
# | |
# instead of | |
# | |
# short = true | |
# super_long_name = true | |
# | |
# Whether this is actually helpful will depend on context. | |
Style/SpaceAroundOperators: | |
MultiSpaceAllowedForOperators: | |
- '=' | |
- '=>' | |
# --- | |
# Preference: it usually looks cleaner to use the space: | |
# | |
# (1..10).map {|n| n ** 2 } | |
# | |
# compared to | |
# | |
# (1..10).map{|n| n ** 2 } | |
# | |
Style/SpaceBeforeBlockBraces: | |
EnforcedStyle: space | |
# --- | |
# Preference: it looks cleaner to omit the space: | |
# | |
# [:thing_one, :thing_two] | |
# | |
# compared to | |
# | |
# [ :thing_one, :thing_two ] | |
# | |
Style/SpaceInsideBrackets: | |
Enabled: true | |
# --- | |
# Preference: blocks look most clear when only arguments butt up against | |
# the opening brace. | |
# | |
# 5.times { puts "iteration!" } # => good! | |
# 5.times {puts "iteration!"} # => weird. | |
# | |
# 5.times {|n| puts "#{n}th iteration!" } # => good! | |
# 5.times { |n| puts "#{n}th iteration!" } # => weird. | |
# | |
Style/SpaceInsideBlockBraces: | |
EnforcedStyle: space | |
SpaceBeforeBlockParameters: no | |
# --- | |
# Space inside the braces of a single-line hash literal is extraneous | |
# and doesn't aid the eye in parsing. | |
# | |
# When we enforce spaces inside braces for blocks (without arguments), | |
# it becomes very clear what you're looking at inside braces if there's | |
# *no* space inside of hash literals. | |
# | |
# {"x" => 4} | |
# | |
# vs | |
# | |
# { "x" => 4 } | |
# | |
# That said, in *most* cases, it's most clear to have a hash literal | |
# span multiple lines. | |
Style/SpaceInsideHashLiteralBraces: | |
EnforcedStyle: no_space | |
EnforcedStyleForEmptyBraces: no_space | |
# --- | |
# When possible, we prefer to use symbols as procs. | |
# | |
# For example: | |
# | |
# # Yuck, so verbose. | |
# (1..10).map {|n| n.to_s } | |
# | |
# # Wow, look at those space savings! | |
# (1..10).map(&:to_s) | |
# | |
Style/SymbolProc: | |
IgnoredMethods: | |
- respond_to | |
# --- | |
# It's generally good practice to have a trailing newline. | |
# | |
# If you butt heads with this cop, you might want to look into | |
# reconfiguring your editor. | |
Style/TrailingBlankLines: | |
EnforcedStyle: final_newline | |
# --- | |
# ### Unenforced Rules | |
# | |
# If you leave a comma out after the last item in a multiline list, | |
# you *will* eventually add another item to the end of the list and | |
# forget to add a comma to the preceding line. Later, you will find | |
# yourself fixing a syntax error. | |
# | |
# Also, if appending to a multiline list requires adding a comma to one | |
# line and then adding another line, your VCS's history will record that | |
# as a two-line change instead of the one-line change it really is. | |
# This will result in bloated diffs and misleading blames. | |
# | |
# The reason that this is unenforced is that Rubocop reports errors | |
# here for multiline *method calls*, too. Since it treats as multiline | |
# even method calls with a single multiline *hash* argument, it suggests | |
# that `})` become `},)`, which is hideous. | |
Style/TrailingComma: | |
# EnforcedStyleForMultiline: comma | |
Enabled: false | |
# --- | |
# The defaults for trivial accessors seem pretty reasonable. | |
# | |
# Disabling `ExactNameMatch` causes the cop to suggest accessors for | |
# things like | |
# | |
# def name | |
# @other_name | |
# end | |
# | |
# which is probably useful, because turning that into an accessor would | |
# be clearer. | |
# | |
# Other than that, we're changing nothing here. See the defaults | |
# [here](https://github.com/bbatsov/rubocop/blob/v0.32.1/config/default.yml#L671). | |
Style/TrivialAccessors: | |
ExactNameMatch: off | |
# --- | |
# Snake case variable names are the standard in Ruby. | |
Style/VariableName: | |
EnforcedStyle: snake_case | |
# --- | |
# There are few cases I can think of in which a `while` or `until` | |
# modifier is clearer than the multiline version. I think the modifier | |
# variant is more unclear the longer the line is. | |
Style/WhileUntilModifier: | |
MaxLineLength: 80 | |
# --- | |
# This cop encourages the use of word arrays when applicable, rather | |
# than more-verbose array literals of quotes strings. | |
# | |
# For example: | |
# | |
# ["here", "are", "some", "words"] | |
# | |
# becomes | |
# | |
# %w(here are some words) | |
# | |
# We keep the default Rubocop regex because it seems sane, but start | |
# enforcing this rule only once you hit an array of three or more | |
# things. Enforcing it for less than that just seems overbearing. | |
Style/WordArray: | |
MinSize: 3 | |
WordRegex: !ruby/regexp '/\A[\p{Word}]+\z/' | |
# ## Metrics | |
# This limits [ABC size](http://c2.com/cgi/wiki?AbcMetric). | |
# | |
# The default of 15 seems to be a little bit too strict. | |
Metrics/AbcSize: | |
Max: 20 | |
# --- | |
# The default maximum for block nesting is 3. That seems reasonable. | |
Metrics/BlockNesting: | |
Max: 3 | |
# --- | |
# A 100-line maximum seems arbitrary and small, but it *is* a good idea | |
# to start complaining about classes and modules getting too large. | |
Metrics/ClassLength: | |
CountComments: no | |
Max: 250 | |
Metrics/ModuleLength: | |
CountComments: no | |
Max: 250 | |
# --- | |
# The default for cyclomatic complexity is 6. | |
# | |
# That seems like it could be low, but we'll try to adhere to it. | |
Metrics/CyclomaticComplexity: | |
Max: 6 | |
# --- | |
# There are a lot of cases where it's obnoxious to constrain lines to 80 | |
# characters because they are more clear than they would be if split up. | |
# | |
# However, there probably *is* a point at which lines become too long to | |
# be clear. Let's hypothesize that that's at 120 characters. | |
Metrics/LineLength: | |
Max: 120 | |
# --- | |
# Many of our enforced rules result in code longer than that encouraged | |
# by Rubocop's default style guide. As a result, we will probably wind up | |
# with longer methods by line than Rubocop expects. | |
# | |
# Rubocop's default is 10; we'll go with double that. | |
Metrics/MethodLength: | |
CountComments: no | |
Max: 20 | |
# --- | |
# If our parameter lists contain more than 4 things, we should be using | |
# an options hash. | |
# | |
# If we have more than 4 *required* arguments, we're building something | |
# truly obnoxious to consume, and we should rethink the interface we're | |
# providing. | |
Metrics/ParameterLists: | |
CountKeywordArgs: yes | |
Max: 4 | |
# --- | |
# The perceived complexity cop tries to measure the complexity that | |
# a method presents to a reader. See [its explanation in the | |
# source](https://github.com/bbatsov/rubocop/blob/v0.32.1/lib/rubocop/cop/metrics/perceived_complexity.rb) | |
# for more information. | |
# | |
# The default maximum score of 7 seems like it could be low but worth | |
# striving for. | |
Metrics/PerceivedComplexity: | |
Max: 7 | |
# ## Linting | |
# See Style/ParenthesesAroundCondition. | |
Lint/AssignmentInCondition: | |
AllowSafeAssignment: yes | |
# --- | |
# The `end` should always be indented consistently with the block level | |
# it ends. That is, | |
# | |
# stylish = if adheres_to_this_guide? | |
# :probably | |
# else | |
# :probably_not | |
# end | |
# | |
# is clear, while | |
# | |
# stylish = if adheres_to_this_guide? | |
# :probably | |
# else | |
# :probably_not | |
# end | |
# | |
# is weird. | |
# | |
# Put differently, if you were to add `end`s to close all of the | |
# contexts you have open, you should have a cascade of `end`s, each of | |
# which is indented two spaces less than the previous, down to 0 spaces | |
# of indentation. | |
# | |
# There might be other cases in which this linter doesn't align things | |
# accordingly, but it's unclear what they are. | |
Lint/EndAlignment: | |
AlignWith: variable | |
AutoCorrect: true | |
# --- | |
# Similar to the previous rule, you should always be able to make | |
# a consistent cascade of `end`s. | |
# | |
# `start_of_line` here means that the `end` will be indented the same as | |
# the line that contains the corresponding `def`, even if the `def` is | |
# preceded by an access modifier like `private` or `protected`. | |
# | |
# Why would you precede the `def` with one of those? Unclear. | |
Lint/DefEndAlignment: | |
AlignWith: start_of_line | |
# --- | |
# You don't *need* to declare block arguments if you don't use them. | |
# | |
# However, it can make the code easier to understand and modify later, | |
# so we don't *require* that you omit arguments that you don't use. | |
Lint/UnusedBlockArgument: | |
Enabled: false | |
# --- | |
# See Lint/UnusedBlockArgument. | |
Lint/UselessAssignment: | |
Enabled: false | |
# ## Rails Cops | |
# `before_action` is more clear than `before_filter`. | |
# | |
# Not all actions are filters, but all filters are actions. | |
# | |
# Additionally, this makes it a little more clear that a "filter" is | |
# responsible for taking the action of redirecting (or returning a 401 | |
# or whatever) if necessary. | |
Rails/ActionFilter: | |
EnforcedStyle: action | |
# --- | |
# If there were a cop that only allowed you to use the most sensible and | |
# correct `Date`/`Time`/`DateTime` methods, we'd enable that. | |
# | |
# This is a good start. But you're still in deep trouble if you have to | |
# deal with time. | |
# | |
# For elaboration on this, see [the | |
# source](https://github.com/bbatsov/rubocop/blob/v0.32.1/lib/rubocop/cop/rails/date.rb). | |
Rails/Date: | |
EnforcedStyle: always | |
# --- | |
# This cop ensures that you pass a block to `default_scope`, not | |
# a Proc. | |
Rails/DefaultScope: | |
Include: | |
- app/controllers/**/*.rb | |
# --- | |
# Building up a query by doing `.where(...)` and *then* retrieving | |
# things from it is consistent and clear. | |
# | |
# I'm in favor of doing `.where(...).first` instead of `.find_by(...)` | |
# to maintain that consistency, if the author thinks that's clearer. | |
# Another advantage of always using `where` is that it becomes easier to | |
# change what you retrieve later. | |
# | |
# There is no performance impact either way, since [`find_by` just does | |
# a `.where.take`, anyway][rails-docs-find-by]. | |
# | |
# This cop would rewrite *any* `.where(...).first` as a `.find_by(...)`, | |
# which is in conflict with that. | |
# | |
# [rails-docs-find-by]: http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find_by | |
Rails/FindBy: | |
Enabled: false | |
# --- | |
# `find_each` is far more efficient when iterating over query results. | |
# From the Rails documentation: | |
# | |
# > Looping through a collection of records from the database (using the all method, for example) is very inefficient since it will try to instantiate all the objects at once. | |
# > | |
# > In that case, batch processing methods allow you to work with the records in batches, thereby greatly reducing memory consumption. | |
# > | |
# > The find_each method uses find_in_batches with a batch size of 1000 (or as specified by the :batch_size option). | |
# | |
# Our setting deviates from the Rubocop default in that it also checks | |
# controllers, Grape API code in `app/api`, DB code (in case we need to | |
# use this in migrations), and Rake tasks. | |
Rails/FindEach: | |
Include: | |
- app/api/**/*.rb | |
- app/controllers/**/*.rb | |
- app/models/**/*.rb | |
- db/**/*.rb | |
- lib/tasks/**/*.rake | |
# --- | |
# This cop prefers `has_many :through` to `has_and_belongs_to_many`. | |
# | |
# We prefer `has_many :through` because it is more explicit and gives us | |
# more control over the join model. | |
Rails/HasAndBelongsToMany: | |
Include: | |
- app/models/**/*.rb | |
# --- | |
# This cop prefers `Rails.logger` calls to standard Ruby output methods. | |
# | |
# We will generally capture stdout and stderr, but we prefer | |
# `Rails.logger` because it gives us on central point of control and | |
# configuration for logging. | |
Rails/Output: | |
Include: | |
- app/**/*.rb | |
- config/**/*.rb | |
- db/**/*.rb | |
- lib/**/*.rb | |
# --- | |
# This cop prefers subscripting to using `read_attribute` or | |
# `write_attribute`. | |
# | |
# It feels a little cleaner to do | |
# | |
# if self[:attributed] | |
# self[:attributed] = false | |
# end | |
# | |
# than | |
# | |
# if read_attribute(:attributed) | |
# write_attribute(:attributed, false) | |
# end | |
# | |
# Our setting differs from the Rubocop default in that it also checks | |
# Grape API code in app/api, controller code, DB code (in the event | |
# that we need to do this in migrations or seeds), and Rake tasks. | |
Rails/ReadWriteAttribute: | |
Include: | |
- app/api/**/*.rb | |
- app/controllers/**/*.rb | |
- app/models/**/*.rb | |
- db/**/*.rb | |
- lib/tasks/**/*.rake | |
# --- | |
# This cop makes sure that we pass a `Proc` into a `scope`, rather than | |
# a plain method call. That is, | |
# | |
# scope :correct, -> { where(uses_proc: true) } | |
# | |
# rather than | |
# | |
# scope :incorrect, where(does_a_method_call_at_definition_time: true) | |
# | |
Rails/ScopeArgs: | |
Include: | |
- app/models/**/*.rb | |
# --- | |
# TL;DR: time zones are awful. In Rails, you should always call your | |
# `Time` API methods on `Time.zone`. | |
# | |
# In fact, the only reason that this is set to "acceptable" is that | |
# there is no "correct" way to parse a timestamp; it's only acceptable | |
# to do `DateTime.strptime(...).in_time_zone`. | |
Rails/TimeZone: | |
EnforcedStyle: acceptable | |
# --- | |
# We prefer the new style of Rails validations to the old. | |
# | |
# That is, | |
# | |
# validates :style, presence: true # => yay! | |
# | |
# validates_presence_of :style # => boo. :-( | |
# | |
Rails/Validation: | |
Include: | |
- app/models/**/*.rb |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This reads better if run through
docco
: