123456789_123456789_123456789_123456789_123456789_

RuboCop can be controlled within your source code using special comments. These directives let you disable or enable cops for specific sections of a file, without changing your <code>.rubocop.yml</code> configuration.

Disabling Cops within Source Code

One or more individual cops can be disabled locally in a section of a file by adding a comment such as

# rubocop:disable Layout/LineLength, Style/StringLiterals
[...]
# rubocop:enable Layout/LineLength, Style/StringLiterals

You can also disable entire departments by giving a department name in the comment.

# rubocop:disable Metrics, Layout/LineLength
[...]
# rubocop:enable Metrics, Layout/LineLength

You can also disable all cops with

# rubocop:disable all
[...]
# rubocop:enable all

In cases where you want to differentiate intentionally-disabled cops vs. cops you’d like to revisit later, you can use <code>rubocop:todo</code> as an alias of <code>rubocop:disable</code>.

# rubocop:todo Layout/LineLength, Style/StringLiterals
[...]
# rubocop:enable Layout/LineLength, Style/StringLiterals

One or more cops can be disabled on a single line with an end-of-line comment.

for x in (0..19) # rubocop:disable Style/For

Disabling Cops for the Next Statement

A <code>disable-next</code> directive on its own line disables the listed cops for the whole statement that follows it - however many lines that statement spans. This avoids both the end-of-line comment (which can push a line over the length limit) and a disable/enable pair around a single construct.

# rubocop:disable-next Metrics/MethodLength
def complicated_method
  # the whole method definition is covered
end

The scope is the next statement, so a method definition, a class body or a loop are each covered in full by a single directive. Everything the other directives support works here too: multiple cops, department names, all, and a trailing <code>--</code> comment. <code>todo-next</code> is the equivalent of <code>rubocop:todo</code>.

Directives on consecutive comment lines stack onto the same statement, which is useful for giving each cop its own justification:

# rubocop:disable-next Metrics/MethodLength -- legacy, tracked in {#123}
# rubocop:disable-next Metrics/AbcSize -- ditto
def complicated_method
end

A blank line breaks the attachment: the directive applies to nothing, and <code>Lint/RedundantCopDisableDirective</code> will flag it, as it does any <code>disable-next</code> whose statement produces no offenses. Unlike disable, a <code>disable-next</code> cannot appear at the end of a code line.

Since only blank lines break the attachment, a <code>disable-next</code> also chains past other directive comments - including <code>rubocop:push</code> and <code>rubocop:pop</code> - and composes with them: inside a pushed scope, a statement is covered by both the pushed settings and any <code>disable-next</code> above it.

If you want to disable a cop that inspects comments, you can do so by adding an "inner comment" on the comment line.

# coding: utf-8 # rubocop:disable Style/Encoding

Running <code>rubocop --autocorrect --disable-uncorrectable</code> will create comments to disable all offenses that can’t be automatically corrected.

You can add a comment to the disabling/enabling directive by prefixing it with <code>--</code>. For example:

# rubocop:disable Layout/LineLength -- A comment explaining why the cop is disabled

The syntax of directives can be checked using the cop <code>Lint/CopDirectiveSyntax</code>.

To see what the directives in a codebase actually suppress, run with --display-suppressed: suppressed offenses are reported tagged <code>[Suppressed]</code> (including their <code>--</code> justification in the JSON formatter) without affecting the exit code. Relatedly, <code>--ignore-disable-comments</code> runs cops as if no directives existed at all.

Temporarily Enabling Cops in Source Code

In a similar way to disabling cops within source code, you can also temporarily enable specific cops if you want to enforce specific rules for part of a file.

Let’s use the cop <code>Style/AsciiComments</code>, which is by default <code>Enabled: false</code>. Say you want a specific file to have ASCII-only comments to be compatible with some post-processing tool:

# rubocop:enable Style/AsciiComments
# If applicable, leave a comment to others explaining the rationale:
# We need the comments to remain ASCII only for compatibility with lib/post_processor.rb

class Restaurant
  # This comment has to be ASCII-only because of the rubocop:enable directive
  def menu
    return dishes.map(&:humanize)
  end
end

You can also enforce the same for part of a file by disabling the cop afterwards

class Dish
  def humanize
    return [
      "Delicious #{self.name}"
      *ingredients
    ].join("\n")
  end
end

# rubocop:enable Style/AsciiComments
# If applicable, leave a comment to others explaining the rationale:
# We need the comments to remain ASCII only for compatibility with lib/post_processor.rb

class Restaurant
  # This comment has to be ASCII-only because of the rubocop:enable directive
  def menu
    return dishes.map(&:humanize)
  end
end

# rubocop:disable Style/AsciiComments

class Ingredient
  # Notice how the comment below is non-ASCII
  # Gets rid of odd characters like 😀, ͸
  def sanitize
    self.name.gsub(/[^a-z]/, '')
  end
end
Note
If a file is excluded via configuration (e.g., in <code>.rubocop.yml</code> or .rubocop_todo.yml), <code>rubocop:enable</code> comments within that file will have no effect. Configuration-based exclusions take precedence over in-source opt-in directives.

Scoped Disabling with Push/Pop Directives

When you want to temporarily change cop settings for a specific section of code and then automatically restore the previous state, you can use <code>rubocop:push</code> and <code>rubocop:pop</code> directives. This is particularly useful when you need to disable cops for a block of code without affecting the rest of the file.

Basic Push/Pop Usage

The push directive saves the current state of all cop settings, and pop restores them:

def process_data(input)
  result = input.upcase
  # rubocop:push
  # rubocop:disable Style/GuardClause
  if result.present?
    return result.strip
  end
  # rubocop:pop
  nil
end

After pop, the <code>Style/GuardClause</code> cop is automatically re-enabled, returning to its state before push.

Inline Push Arguments

For convenience, you can combine push with enable/disable operations using inline arguments. Use - to disable a cop and + to enable a cop:

def process_data(input)
  result = input.upcase
  # rubocop:push -Style/GuardClause
  if result.present?
    return result.strip
  end
  # rubocop:pop
  nil
end

You can specify multiple cops with different operations:

# rubocop:disable Style/For
for x in [1, 2, 3]
  puts x
end
# rubocop:push +Style/For -Style/GuardClause
for y in [4, 5, 6]  # Style/For is re-enabled here
  if y > 0
    return y        # Style/GuardClause is disabled here
  end
end
# rubocop:pop
# Back to original state: Style/For disabled, Style/GuardClause enabled

Nested Push/Pop

Push/pop directives can be nested for complex scenarios:

# rubocop:disable Metrics/MethodLength
def complex_method
  step1
  # rubocop:push
  # rubocop:enable Metrics/MethodLength
  # rubocop:disable Style/GuardClause
  def helper_method
    # rubocop:push
    # rubocop:enable Style/GuardClause
    if condition
      return value
    end
    # rubocop:pop
    other_code
  end
  # rubocop:pop
  step2
end

Each pop restores the state to what it was at the corresponding push.

Choosing a Directive Form

The forms are ordered here from the tightest scope to the widest - prefer the tightest one that fits, since it suppresses the least and cannot drift as the code around it changes:

  • End-of-line disable - a single offense on a single line. The most common form. Reach for the next one when the comment would push the line over the length limit, or when several cops need separate justifications.

  • disable-next - everything about one statement, however many lines it spans: a method definition, a class body, a loop. The scope is derived from the code itself, so it never needs re-adjusting when the statement grows or shrinks.

  • disable / enable pair - an explicit region spanning several statements. The boundaries are yours to maintain: Lint/MissingCopEnableDirective guards against forgetting the closing enable.

  • push / pop - a region where you change several settings at once (disabling some cops, enabling others) and want the previous state restored exactly, including inside nested scopes. Unlike a disable/enable pair, pop cannot get the restored state wrong, because it never states it - it restores whatever was saved.

todo and <code>todo-next</code> are aliases of disable and <code>disable-next</code> that mark a suppression you intend to revisit rather than a deliberate exception.

The <code>Style/DirectiveScope</code> cop can enforce the tightest-form preference: it flags disable/enable pairs and disable-only push/pop scopes that wrap a single statement, and converts them to <code>disable-next</code>.