Configuration
The behavior of RuboCop can be controlled via the .rubocop.yml configuration file. It makes it possible to enable/disable certain cops (checks) and to alter their behavior if they accept any parameters. The file can be placed in your home directory, XDG config directory, or in some project directory.
The file has the following format:
inherit_from: ../.rubocop.yml
Style/Encoding:
Enabled: false
Layout/LineLength:
Max: 99
Qualifying cop name with its type, e.g., Style , is recommended,
but not necessary as long as the cop name is unique across all types.
|
Config file locations
RuboCop will start looking for the configuration file in the directory where the inspected file is and continue its way up to the root directory.
If it cannot be found until reaching the project’s root directory, then it will be searched for in the .config directory of the project root and the user’s global config locations. The user’s global config locations consist of a dotfile or a config file inside the XDG Base Directory specification.
-
.config/.rubocop.yml
or.config/rubocop/config.yml
at the project root -
~/.rubocop.yml
-
$XDG_CONFIG_HOME/rubocop/config.yml
(expands to~/.config/rubocop/config.yml
if$XDG_CONFIG_HOME
is not set)
If both files exist, the dotfile will be selected.
As an example, if RuboCop is invoked from inside /path/to/project/lib/utils
,
then RuboCop will use the config as specified inside the first of the following
files:
-
/path/to/project/lib/utils/.rubocop.yml
-
/path/to/project/lib/.rubocop.yml
-
/path/to/project/.rubocop.yml
-
/path/to/project/.config/.rubocop.yml
-
/path/to/project/.config/rubocop/config.yml
-
/.rubocop.yml
-
~/.rubocop.yml
-
~/.config/rubocop/config.yml
All the previous logic does not apply if a specific configuration file is passed
on the command line through the --config flag. In that case, the resolved
configuration file will be the one passed to the CLI.
|
Inheritance
All configuration inherits from RuboCop’s default configuration (See "Defaults").
RuboCop also supports inheritance in user’s configuration files. The most common
example would be the .rubocop_todo.yml
file (See "Automatically Generated
Configuration" below).
Settings in the child file (that which inherits) override those in the parent (that which is inherited), with the following caveats.
Inheritance of hashes vs. other types
Configuration parameters that are hashes, for example PreferredMethods
in
Style/CollectionMethods
, are merged with the same parameter in the parent
configuration. This means that any key-value pairs given in child configuration
override the same keys in parent configuration. Giving ~
, YAML’s
representation of nil
, as a value cancels the setting of the corresponding
key in the parent configuration. For example:
Style/CollectionMethods:
Enabled: true
PreferredMethods:
# No preference for collect, keep all others from default config.
collect: ~
Other types, such as AllCops
/ Include
(an array), are overridden by the
child setting.
Arrays override because if they were merged, there would be no way to remove elements in child files.
However, advanced users can still merge arrays using the inherit_mode
setting.
See "Merging arrays using inherit_mode" below.
Inheriting from another configuration file in the project
The optional inherit_from
directive is used to include configuration
from one or more files. This makes it possible to have the common
project settings in the .rubocop.yml
file at the project root, and
then only the deviations from those rules in the subdirectories. The
files can be given with absolute paths or paths relative to the file
where they are referenced. The settings after an inherit_from
directive override any settings in the file(s) inherited from. When
multiple files are included, the first file in the list has the lowest
precedence and the last one has the highest. The format for multiple
inheritance is:
inherit_from:
- ../.rubocop.yml
- ../conf/.rubocop.yml
inherit_from
also accepts a glob, for example:
inherit_from:
- packages/*/.rubocop_todo.yml
The example above is one potential use-case: allowing components within your repo to organize their own .rubocop_todo.yml
files.
Inheriting configuration from a remote URL
The optional inherit_from
directive can contain a full url to a remote
file. This makes it possible to have common project settings stored on a http
server and shared between many projects.
The remote config file is cached locally and is only updated if:
-
The file does not exist.
-
The file has not been updated in the last 24 hours.
-
The remote copy has a newer modification time than the local copy.
You can inherit from both remote and local files in the same config and the same inheritance rules apply to remote URLs and inheriting from local files where the first file in the list has the lowest precedence and the last one has the highest. The format for multiple inheritance using URLs is:
inherit_from:
- http://www.example.com/rubocop.yml
- ../.rubocop.yml
You can inherit from a repo with basic auth that is authorized to access the repo as follow:
inherit_from:
- http://<user_name>:<password>@raw.github.com/example/rubocop.yml
A GitHub personal access token can also be configured as follow:
inherit_from:
- http://<personal_access_token>@raw.github.com/example/rubocop.yml
Inheriting configuration from a dependency gem
The optional inherit_gem
directive is used to include configuration from
one or more gems external to the current project. This makes it possible to
inherit a shared dependency’s RuboCop configuration that can be used from
multiple disparate projects.
Configurations inherited in this way will be essentially prepended to the
inherit_from
directive, such that the inherit_gem
configurations will be
loaded first, then the inherit_from
relative file paths will be loaded
(overriding the configurations from the gems), and finally the remaining
directives in the configuration file will supersede any of the inherited
configurations. This means the configurations inherited from one or more gems
have the lowest precedence of inheritance.
The directive should be formatted as a YAML Hash using the gem name as the key and the relative path within the gem as the value:
inherit_gem:
my-shared-gem: .rubocop.yml
cucumber: conf/rubocop.yml
An array can also be used as the value to include multiple configuration files from a single gem:
inherit_gem:
my-shared-gem:
- default.yml
- strict.yml
If the shared dependency is declared using a Bundler
Gemfile and the gem was installed using bundle install , it would be
necessary to also invoke RuboCop using Bundler in order to find the
dependency’s installation path at runtime:
|
$ bundle exec rubocop <options...>
Merging arrays using inherit_mode
The optional directive inherit_mode
specifies which configuration keys that
have array values should be merged together instead of overriding the inherited
value.
This applies to explicit inheritance using inherit_from
as well as implicit
inheritance from the default configuration.
Given the following config:
# .rubocop.yml
inherit_from:
- shared.yml
inherit_mode:
merge:
- Exclude
AllCops:
Exclude:
- 'generated/**/*.rb'
Style/For:
Exclude:
- bar.rb
# .shared.yml
Style/For:
Exclude:
- foo.rb
The list of Exclude
s for the Style/For
cop in this example will be
['foo.rb', 'bar.rb']
. Similarly, the AllCops:Exclude
list will contain all
the default patterns plus the generated/**/*.rb
entry that was added locally.
The directive can also be used on individual cop configurations to override the global setting.
inherit_from:
- shared.yml
inherit_mode:
merge:
- Exclude
Style/For:
inherit_mode:
override:
- Exclude
Exclude:
- bar.rb
In this example the Exclude
would only include bar.rb
.
Pre-processing
Configuration files are pre-processed using the ERB templating mechanism. This makes it possible to add dynamic content that will be evaluated when the configuration file is read. For example, you could let RuboCop ignore all files ignored by Git.
AllCops:
Exclude:
<% `git status --ignored --porcelain`.lines.grep(/^!! /).each do |path| %>
- <%= path.sub(/^!! /, '').sub(/\/$/, '/**/*') %>
<% end %>
Defaults
The file config/default.yml under the RuboCop home directory contains the
default settings that all configurations inherit from. Project and personal
.rubocop.yml
files need only make settings that are different from the
default ones. If there is no .rubocop.yml
file in the project, home or XDG
directories, config/default.yml
will be used.
Including/Excluding files
RuboCop does a recursive file search starting from the directory it is
run in, or directories given as command line arguments. Files that
match any pattern listed under AllCops
/Include
and extensionless
files with a hash-bang (#!
) declaration containing one of the known
ruby interpreters listed under AllCops
/RubyInterpreters
are
inspected, unless the file also matches a pattern in
AllCops
/Exclude
. Hidden directories (i.e., directories whose names
start with a dot) are not searched by default.
Here is an example that might be used for a Rails project:
AllCops:
Exclude:
- 'db/**/*'
- 'config/**/*'
- 'script/**/*'
- 'bin/{rails,rake}'
- !ruby/regexp /old_and_unused\.rb$/
# other configuration
# ...
When inspecting a certain directory(or file)
given as RuboCop’s command line arguments,
patterns listed under AllCops / Exclude are also inspected.
If you want to apply AllCops / Exclude rules in this circumstance,
add --force-exclusion to the command line argument.
|
Here is an example:
# .rubocop.yml
AllCops:
Exclude:
- foo.rb
If foo.rb
specified as a RuboCop’s command line argument, the result is:
# RuboCop inspects foo.rb.
$ bundle exec rubocop foo.rb
# RuboCop does not inspect foo.rb.
$ bundle exec rubocop --force-exclusion foo.rb
Path relativity
In .rubocop.yml
and any other configuration file beginning with .rubocop
,
files, and directories are specified relative to the directory where the
configuration file is. In configuration files that don’t begin with .rubocop
,
e.g. our_company_defaults.yml
, paths are relative to the directory where
rubocop
is run.
This affects cops that have customisable paths: if the default is db/migrate/*.rb
,
and the cop is enabled in db/migrate/.rubocop.yml
, the path will need to be
explicitly set as *.rb
, as the default will look for db/migrate/db/migrate/*.rb
.
This is unlikely to be what you wanted.
Unusual files, that would not be included by default
RuboCop comes with a comprehensive list of common ruby file names and
extensions. But, if you’d like RuboCop to check files that are not included by
default, you’ll need to pass them in on the command line, or to add entries for
them under AllCops
/Include
. Remember that your configuration files override
RuboCops’s defaults. In the following example, we want to include
foo.unusual_extension
, but we also must copy any other patterns we need from
the overridden default.yml
.
AllCops:
Include:
- foo.unusual_extension
- '**/*.rb'
- '**/*.gemfile'
- '**/*.gemspec'
- '**/*.rake'
- '**/*.ru'
- '**/Gemfile'
- '**/Rakefile'
Deprecated patterns
Patterns that are just a file name, e.g. Rakefile
, will match
that file name in any directory, but this pattern style is deprecated. The
correct way to match the file in any directory, including the current, is
**/Rakefile
.
The pattern config/**
will match any file recursively under
config
, but this pattern style is deprecated and should be replaced by
config/**/*
.
Include
and Exclude
are relative to their directory
The Include
and Exclude
parameters are special. They are
valid for the directory tree starting where they are defined. They are not
shadowed by the setting of Include
and Exclude
in other .rubocop.yml
files in subdirectories. This is different from all other parameters, who
follow RuboCop’s general principle that configuration for an inspected file
is taken from the nearest .rubocop.yml
, searching upwards.
This behavior
will be overridden if you specify the --ignore-parent-exclusion command line
argument.
|
Cop-specific Include
and Exclude
Cops can be run only on specific sets of files when that’s needed (for
instance you might want to run some Rails model checks only on files whose
paths match app/models/*.rb
). All cops support the
Include
param.
Rails/HasAndBelongsToMany:
Include:
- app/models/*.rb
Cops can also exclude only specific sets of files when that’s needed (for
instance you might want to run some cop only on a specific file). All cops support the
Exclude
param.
Rails/HasAndBelongsToMany:
Exclude:
- app/models/problematic.rb
Generic configuration parameters
In addition to Include
and Exclude
, the following parameters are available
for every cop.
Enabled
Specific cops can be disabled by setting Enabled
to false
for that specific cop.
Layout/LineLength:
Enabled: false
Most cops are enabled by default. Cops, introduced or significantly updated
between major versions, are in a special pending status (read more in
"Versioning"). Some cops, configured the above Enabled: false
in config/default.yml,
are disabled by default.
The cop enabling process can be altered by setting DisabledByDefault
or
EnabledByDefault
(but not both) to true
. These settings override the default for all
cops to disabled or enabled, except Lint/Syntax
which is always enabled,
regardless of the cops' default values (whether enabled, disabled or pending).
AllCops:
DisabledByDefault: true
All cops except Lint/Syntax
are then disabled by default. Only cops appearing in user
configuration files with Enabled: true
will be enabled; every other cop will
be disabled without having to explicitly disable them in configuration. It is
also possible to enable entire departments by adding for example
Style:
Enabled: true
All cops in the Style
department are then enabled. In this case, only the cops
in the Style
department that are enabled by default will be enabled.
The cops in the Style
department that are disabled by default will remain disabled.
If a department is disabled, cops in that department can still be individually enabled, and that setting overrides the setting for its department in the same configuration file and in any inherited file.
inherit_from: config_that_disables_the_metrics_department.yml
Metrics/MethodLength:
Enabled: true
Style:
Enabled: false
Style/Alias:
Enabled: true
Severity
Each cop has a default severity level based on which department it belongs
to. The level is normally warning
for Lint
and convention
for all the
others, but this can be changed in user configuration. Cops can customize their
severity level. Allowed values are info
, refactor
, convention
, warning
, error
and fatal
.
Cops with severity info
will be reported but will not cause rubocop
to return
a non-zero value.
There is one exception from the general rule above and that is Lint/Syntax
, a
special cop that checks for syntax errors before the other cops are invoked. It
cannot be disabled and its severity (fatal
) cannot be changed in
configuration.
Lint:
Severity: error
Metrics/CyclomaticComplexity:
Severity: warning
Details
Individual cops can be embellished with extra details in offense messages:
Layout/LineLength:
Details: >-
If lines are too short, text becomes hard to read because you must
constantly jump from one line to the next while reading. If lines are too
long, the line jumping becomes too hard because you "lose the line" while
going back to the start of the next line. 80 characters is a good
compromise.
These details will only be seen when RuboCop is run with the --extra-details
flag or if ExtraDetails
is set to true in your global RuboCop configuration.
AutoCorrect
Cops that support the --autocorrect
option offer flexible settings for autocorrection.
These settings can be specified in the configuration file as follows:
-
always
-
contextual
-
disabled
always (Default)
This setting enables autocorrection always by default. For backward compatibility, true
is treated the same as always
.
Style/PerlBackrefs:
AutoCorrect: always # or true
contextual
This setting enables autocorrection when launched from the rubocop
command, but it is not available through LSP.
e.g., rubocop --lsp
, rubocop --editor-mode
, or a program where RuboCop::LSP.enable
has been applied.
Inspections via the command line are treated as code that has been finalized.
Style/PerlBackrefs:
AutoCorrect: contextual
This setting prevents autocorrection during editing in the editor. e.g, with textDocument/formatting
LSP method.
However workspace/executeCommand
LSP method, which is triggered by intentional user actions, respects the user’s intention for autocorrection.
Additionally, for cases like Metrics
cops where the highlight range extends over the entire body of classes, modules, methods, or blocks
offending range will be confined to only name. This approach helps to avoid redundant and noisy offenses in editor display.
Common configuration parameters
There are some configuration parameters that are shared by many cops, with the same behavior.
Setting the target Ruby version
Some checks are dependent on the version of the Ruby interpreter which the
inspected code must run on. For example, enforcing using Ruby 2.6+ endless
ranges foo[n..]
rather than foo[n..-1]
can help make your code shorter and
more consistent… unless it must run on e.g. Ruby 2.5.
Users may let RuboCop know the oldest version of Ruby which your project supports with:
AllCops:
TargetRubyVersion: 2.5
When ParserEngine: parser_prism is specified, TargetRubyVersion must
be set to 3.3 or higher.
|
If a TargetRubyVersion
is not specified in your config, then RuboCop will
check your project for a series of other files where the Ruby version may be
specified already. The files that will be checked are (in this order):
*.gemspec
, .ruby-version
, .tool-versions
, and Gemfile.lock
.
If a target Ruby version cannot be found via any of the above sources, then a default target Ruby version will be used.
Finding target Ruby in a *.gemspec
file
In order for RuboCop to parse a *.gemspec
file’s required_ruby_version
, the
Ruby version must be specified using one of these syntaxes:
-
a string range, e.g.
'~> 3.2.0'
or'>= 3.2.2'
-
an array of strings, e.g.
['>= 3.0.0', '< 3.4.0']
-
a
Gem::Requirement
, e.g.Gem::Requirement.new('>= 3.1.2')
If a *.gemspec
file specifies a range of supported Ruby versions via any of
these means, then the greater of the following Ruby versions will be used:
-
the lowest Ruby version that is compatible with your specified range
-
the lowest version of Ruby that is still supported by your version of RuboCop
If a *.gemspec
file defines its required_ruby_version
dynamically (e.g. by
reading from a .ruby-version
file, via an environment variable, referencing a
constant or local variable, etc), then RuboCop will not detect that Ruby
version, and will instead try to find a target Ruby version elsewhere.
Setting the parser engine
The parser engine configuration was introduced in RuboCop 1.62. This experimental feature has been under consideration for a while. |
RuboCop allows switching the backend parser by specifying either
parser_whitequark
or parser_prism
as the value for the ParserEngine
.
Here are the parsers used as backends for each value:
-
ParserEngine: parser_whitequark
… https://github.com/whitequark/parser -
ParserEngine: parser_prism
… https://github.com/ruby/prism (Prism::Translation::Parser
)
By default, parser_whitequark
is implicitly used.
parser_whitequark
can analyze source code from Ruby 2.0 and above:
AllCops:
ParserEngine: parser_whitequark
parser_prism
can analyze source code from Ruby 3.3 and above:
AllCops:
ParserEngine: parser_prism
TargetRubyVersion: 3.3
parser_prism
tends to perform analysis faster than parser_whitequark
.
Since the support for Prism is experimental, it is not included in
RuboCop’s runtime dependencies. If running RuboCop through Bundler, please add
gem 'prism' to your Gemfile :
|
gem 'prism'
There are some incompatibilities with parser_whitequark
in parser_prism
,
which is the main reason why the support for it is considered experimental.
We’re working with Prism’s team to address those. You can track the outstanding
known issues in Prism that affect RuboCop
here.
Automatically Generated Configuration
If you have a code base with an overwhelming amount of offenses, it can
be a good idea to use rubocop --auto-gen-config
, which creates
.rubocop_todo.yml
and adds inherit_from: .rubocop_todo.yml
in your
.rubocop.yml
. The generated file .rubocop_todo.yml
contains
configuration to disable cops that currently detect an offense in the
code by changing the configuration for the cop, excluding the offending
files, or disabling the cop altogether once a file count limit has been
reached.
By adding the option --exclude-limit COUNT
, e.g., rubocop
--auto-gen-config --exclude-limit 5
, you can change how many files are
excluded before the cop is entirely disabled. The default COUNT is 15.
If you don’t want the cop to be entirely disabled regardless of the
number of files, use the --no-exclude-limit
option, e.g.,
rubocop --auto-gen-config --no-exclude-limit
.
The next step is to cut and paste configuration from .rubocop_todo.yml
into .rubocop.yml
for everything that you think is in line with your
(organization’s) code style and not a good fit for a todo list. Pay
attention to the comments above each entry. They can reveal configuration
parameters such as EnforcedStyle
, which can be used to modify the
behavior of a cop instead of disabling it completely.
Then you can start removing the entries in the generated
.rubocop_todo.yml
file one by one as you work through all the offenses
in the code. You can also regenerate your .rubocop_todo.yml
using
the same options by running rubocop --regenerate-todo
.
Another way of silencing offense reports, aside from configuration, is through source code comments. These can be added manually or automatically. See "Disabling Cops within Source Code" below.
The cops in the Metrics
department will by default get Max
parameters
generated in .rubocop_todo.yml
. The value of these will be just high enough
so that no offenses are reported the next time you run rubocop
. If you
prefer to exclude files, like for other cops, add --auto-gen-only-exclude
when running with --auto-gen-config
. It will still change the maximum if the
number of excluded files is higher than the exclude limit.
Some cops have a configurable option named EnforcedStyle
.
By default, when generating the .rubocop_todo.yml
, if one style is used
for all files, these cops will add the settings for the style being used.
If you want to excluded on a file-by-file basis,
add the --no-auto-gen-enforced-style
option along with --auto-gen-config
.
Updating the configuration file
When you update RuboCop version, sometimes you need to change .rubocop.yml
.
If you use mry, you can update .rubocop.yml
to latest version automatically.
$ gem install mry
# Update to latest version
$ mry .rubocop.yml
# Update to specified version
$ mry --target=0.48.0 .rubocop.yml
See https://github.com/pocke/mry for more information.
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 rubocop:todo
as an alias of
rubocop:disable
.
# 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
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 rubocop --autocorrect --disable-uncorrectable
will
create comments to disable all offenses that can’t be automatically
corrected.
Do not write anything other than cop name in the disabling comment. E.g.:
# rubocop:disable Layout/LineLength --This is a bad comment that includes other than cop name.
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 the totality of a file.
Let’s use the cop Style/AsciiComments
, which is by default Enabled: false
. If you want a
specific file to have ASCII-only comments to be compatible with some specific post-processing.
# 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
Setting the style guide URL
You can specify the base URL of the style guide using StyleGuideBaseURL
.
If specified under AllCops
, all cops are targeted.
AllCops:
StyleGuideBaseURL: https://rubystyle.guide
StyleGuideBaseURL
is combined with StyleGuide
specified to the cop.
Lint/UselessAssignment:
StyleGuide: '#underscore-unused-vars'
The style guide URL is https://rubystyle.guide#underscore-unused-vars.
If specified under a specific department, it takes precedence over AllCops
.
The following is an example of specifying Rails
department.
Rails:
StyleGuideBaseURL: https://rails.rubystyle.guide
Rails/TimeZone:
StyleGuide: '#time'
The style guide URL is https://rails.rubystyle.guide#time.
Setting the documentation URL
You can specify the base URL of the documentation using DocumentationBaseURL
.
If specified under AllCops
, all cops are targeted.
AllCops:
DocumentationBaseURL: https://docs.rubocop.org/rubocop
If specified under a specific department, it takes precedence over AllCops
.
The following is an example of specifying Rails
department.
Rails:
DocumentationBaseURL: https://docs.rubocop.org/rubocop-rails
By default, documentation is expected to be served as HTML but if you prefer
to use something else like markdown you can set DocumentationExtension
.
With markdown as the documentation format you are able to host it directly through
GitHub without having to own a domain or using GitHub Pages. The rubocop-sorbet
extension is an example of this, its docs are available
here.
Sorbet:
DocumentationBaseURL: https://github.com/Shopify/rubocop-sorbet/blob/main/manual
DocumentationExtension: .md
Enable checking Active Support extensions
Some cops for checking specified methods (e.g. Style/HashExcept
) supports Active Support extensions.
This is off by default, but can be enabled by the ActiveSupportExtensionsEnabled
option.
AllCops:
ActiveSupportExtensionsEnabled: true
Opting into globally frozen string literals
Ruby continues to move into the direction of having all string literals frozen by default.
Ruby 3.4 for example will show a warning if a non-frozen string literal from a file without
the frozen string literal magic comment gets modified. By starting ruby with the environment
variable RUBYOPT
set to --enable=frozen-string-literal
you can opt into that behaviour today.
For RuboCop to provide accurate analysis you must also configure the StringLiteralsFrozenByDefault
option.
AllCops:
StringLiteralsFrozenByDefault: true