Role models are important.
-- Officer Alex J. Murphy / RoboCop
RuboCop is a Ruby static code analyzer. Out of the box it will enforce many of the guidelines outlined in the community Ruby Style Guide.
Most aspects of its behavior can be tweaked via various configuration options.
Apart from reporting problems in your code, RuboCop can also automatically fix some of the problems for you.
- Installation
- Basic Usage
- Configuration
- Disabling Cops within Source Code
- Formatters
- Compatibility
- Editor integration
- Guard integration
- Rake integration
- Team
- Contributors
- Mailing List
- Changelog
- Copyright
RuboCop's installation is pretty standard:
$ gem install rubocop
If you'd rather install RuboCop using bundler
, don't require it in your Gemfile
:
gem 'rubocop', require: false
Running rubocop
with no arguments will check all Ruby source files
in the current directory:
$ rubocop
Alternatively you can pass rubocop
a list of files and directories to check:
$ rubocop app spec lib/something.rb
Here's RuboCop in action. Consider the following Ruby source code:
def badName
if something
test
end
end
Running RuboCop on it (assuming it's in a file named test.rb
) would produce the following report:
Offenses:
test.rb:1:5: C: Use snake_case for methods and variables.
def badName
^^^^^^^
test.rb:2:3: C: Favor modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/||.
if something
^^
test.rb:4:5: W: end at 4, 4 is not aligned with if at 2, 2
end
^^^
1 file inspected, 3 offenses detected
For more details check the available command-line options:
$ rubocop -h
Command flag | Description |
---|---|
-v/--version |
Displays the current version and exits |
-V/--verbose-version |
Displays the current version plus the version of Parser and Ruby |
-d/--debug |
Displays some extra debug output |
-D/--display-cop-names |
Displays cop names in offense messages. |
-c/--config |
Run with specified config file |
-f/--format |
Choose a formatter |
-o/--out |
Write output to a file instead of STDOUT |
-r/--require |
Require Ruby file |
-R/--rails |
Run extra Rails cops |
-l/--lint |
Run only lint cops |
-a/--auto-correct |
Auto-correct certain offenses Note: Experimental - use with caution |
--only |
Run only the specified cop |
--auto-gen-config |
Generate a configuration file acting as a TODO list |
--show-cops |
Shows available cops and their configuration |
--fail-level |
Minimum severity for exit with error code |
In RuboCop lingo the various checks performed on the code are called cops. There are several cop departments.
Most of the cops in RuboCop are so called style cops that check for stylistics problems in your code. Almost all of the them are based on the Ruby Style Guide. Many of the style cops have configurations options allowing them to support different popular coding conventions.
Lint cops check for possible errors and very bad practices in your
code. RuboCop implements in a portable way all built-in MRI lint
checks (ruby -wc
) and adds a lot of extra lint checks of its
own. You can run only the lint cops like this:
$ rubocop -l
Disabling any of the lint cops is generally a bad idea.
Rails cops are specific to the Ruby on Rails framework. Unlike style and lint cops they are not used by default and you have to request them specifically:
$ rubocop -R
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 either in your home directory or in some project directory.
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.
The file has the following format:
inherit_from: ../.rubocop.yml
Encoding:
Enabled: false
LineLength:
Max: 99
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
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 or home
directory, config/default.yml
will be used.
RuboCop checks all files recursively within the directory it is run
on. However, it only recognizes files ending with .rb
or
extensionless files with a #!.*ruby
declaration as Ruby files. If
you'd like it to check other files you'll need to manually pass them
in, or to add entries for them under AllCops
/Include
. Files and
directories can also be ignored through AllCops
/Exclude
.
Here is an example that might be used for a Rails project:
AllCops:
Include:
- Rakefile
- config.ru
Exclude:
- db/**
- config/**
- script/**
- !ruby/regexp /old_and_unused\.rb$/
# other configuration
# ...
Files and directories are specified relative to the .rubocop.yml
file.
Note: The Exclude
parameter is special. It is valid for the
directory tree starting where it is defined. It is not shadowed by the
setting of 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.
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.
DefaultScope:
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.
DefaultScope:
Exclude:
- app/models/problematic.rb
Specific cops can be disabled by setting Enabled
to false
for that specific cop.
LineLength:
Enabled: false
Cops can customize their severity level. All cops support the Severity
param.
Allowed params are refactor
, convention
, warning
, error
and fatal
.
CyclomaticComplexity:
Severity: warning
If you have a code base with an overwhelming amount of offenses, it can be a
good idea to use rubocop --auto-gen-config
and add an inherit_from: rubocop-todo.yml
in your .rubocop.yml
. The generated file rubocop-todo.yml
contains configuration to disable all cops that currently detect an offense in
the code. Then you can start removing the entries in the generated file one by
one as you work through all the offenses in the code.
One or more individual cops can be disabled locally in a section of a file by adding a comment such as
# rubocop:disable LineLength, StringLiterals
[...]
# rubocop:enable LineLength, StringLiterals
You can also disable all cops with
# rubocop:disable all
[...]
# rubocop:enable all
One or more cops can be disabled on a single line with an end-of-line comment.
for x in (0..19) # rubocop:disable AvoidFor
You can change the output format of RuboCop by specifying formatters with the -f/--format
option.
RuboCop ships with several built-in formatters, and also you can create your custom formatter.
Additionaly the output can be redirected to a file instead of $stdout
with the -o/--out
option.
Some of the built-in formatters produce machine-parsable output and they are considered public APIs. The rest of the formatters are for humans, so parsing their outputs is discouraged.
You can enable multiple formatters at the same time by specifying -f/--format
multiple times.
The -o/--out
option applies to the previously specified -f/--format
,
or the default progress
format if no -f/--format
is specified before the -o/--out
option.
# Simple format to $stdout.
$ rubocop --format simple
# Progress (default) format to the file result.txt.
$ rubocop --out result.txt
# Both progress and offense count formats to $stdout.
# The offense count formatter outputs only the final summary,
# so you'll mostly see the outputs from the progress formatter,
# and at the end the offense count summary will be outputted.
$ rubocop --format progress --format offenses
# Progress format to $stdout, and JSON format to the file rubocop.json.
$ rubocop --format progress --format json --out rubocop.json
# ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
# | |_______________|
# $stdout
# Progress format to result.txt, and simple format to $stdout.
$ rubocop --output result.txt --format simple
# ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
# | |
# default format $stdout
The default progress
formatter outputs a character for each inspected file,
and at the end it displays all detected offenses in the clang
format.
A .
represents a clean file, and each of the capital letters means
the severest offense (convention, warning, error or fatal) found in a file.
$ rubocop
Inspecting 26 files
..W.C....C..CWCW.C...WC.CC
Offenses:
lib/foo.rb:6:5: C: Missing top-level class documentation comment.
class Foo
^^^^^
...
26 files inspected, 46 offenses detected
The clang
formatter displays the offenses in a manner similar to clang
:
$ rubocop test.rb
test.rb:1:1: C: Use snake_case for methods and variables.
def badName
^^^^^^^
test.rb:2:3: C: Favor modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/||.
if something
^^
test.rb:4:5: W: end at 4, 4 is not aligned with if at 2, 2
end
^^^
1 file inspected, 3 offenses detected
The fuubar
style formatter displays a progress bar
and shows details of offenses in the clang
format as soon as they are detected.
This is inspired by the Fuubar formatter for RSpec.
$ rubocop --format fuubar
lib/foo.rb.rb:1:1: C: Use snake_case for methods and variables.
def badName
^^^^^^^
lib/bar.rb:13:14: W: File.exists? is deprecated in favor of File.exist?.
File.exists?(path)
^^^^^^^
22/53 files |======== 43 ========> | ETA: 00:00:02
Machine-parsable
The emacs
formatter displays the offenses in a format suitable for consumption by Emacs
(and possibly other tools).
$ rubocop --format emacs test.rb
/Users/bozhidar/projects/test.rb:1:1: C: Use snake_case for methods and variables.
/Users/bozhidar/projects/test.rb:2:3: C: Favor modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/||.
/Users/bozhidar/projects/test.rb:4:5: W: end at 4, 4 is not aligned with if at 2, 2
The name of the formatter says it all :-)
$ rubocop --format simple test.rb
== test.rb ==
C: 1: 1: Use snake_case for methods and variables.
C: 2: 3: Favor modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/||.
W: 4: 5: end at 4, 4 is not aligned with if at 2, 2
1 file inspected, 3 offenses detected
Machine-parsable
Sometimes you might want to just open all files with offenses in your favorite editor. This formatter outputs just the names of the files with offenses in them and makes it possible to do something like:
$ rubocop --format files | xargs vim
Machine-parsable
You can get RuboCop's inspection result in JSON format by passing --format json
option in command line.
The JSON structure is like the following example:
{
"metadata": {
"rubocop_version": "0.9.0",
"ruby_engine": "ruby",
"ruby_version": "2.0.0",
"ruby_patchlevel": "195",
"ruby_platform": "x86_64-darwin12.3.0"
},
"files": [{
"path": "lib/foo.rb",
"offenses": []
}, {
"path": "lib/bar.rb",
"offenses": [{
"severity": "convention",
"message": "Line is too long. [81/79]",
"cop_name": "LineLength",
"corrected": true,
"location": {
"line": 546,
"column": 80,
"length": 4
}
}, {
"severity": "warning",
"message": "Unreachable code detected.",
"cop_name": "UnreachableCode",
"corrected": false,
"location": {
"line": 15,
"column": 9,
"length": 10
}
}
]
}
],
"summary": {
"offense_count": 2,
"target_file_count": 2,
"inspected_file_count": 2
}
}
Sometimes when first applying RuboCop to a codebase, it's nice to be able to see where most of your style cleanup is going to be spent.
With this in mind, you can use the offense count formatter to outline the offended cops and the number of offenses found for each by running:
$ rubocop --format offenses
87 Documentation
12 DotPosition
8 AvoidGlobalVars
7 EmptyLines
6 AssignmentInCondition
4 Blocks
4 CommentAnnotation
3 BlockAlignment
1 IndentationWidth
1 AvoidPerlBackrefs
1 ColonMethodCall
--
134 Total
You can customize RuboCop's output format with custom formatter.
To implement a custom formatter, you need to subclass
Rubocop::Formatter::BaseFormatter
and override some methods,
or implement all formatter API methods by duck typing.
Please see the documents below for more formatter API details.
You can tell RuboCop to use your custom formatter with a combination of
--format
and --require
option.
For example, when you have defined MyCustomFormatter
in
./path/to/my_custom_formatter.rb
, you would type this command:
$ rubocop --require ./path/to/my_custom_formatter --format MyCustomFormatter
Note: The path passed to --require
is directly passed to Kernel.require
.
If your custom formatter file is not in $LOAD_PATH
,
you need to specify the path as relative path prefixed with ./
explicitly,
or absolute path.
RuboCop supports the following Ruby implementations:
- MRI 1.9.2 (until June 2014)
- MRI 1.9.3
- MRI 2.0
- MRI 2.1
- JRuby in 1.9 mode
- Rubinius 2.0+
rubocop.el is a simple Emacs interface for RuboCop. It allows you to run RuboCop inside Emacs and quickly jump between problems in your code.
flycheck > 0.9 also supports RuboCop and uses it by default when available.
The vim-rubocop plugin runs RuboCop and displays the results in Vim.
There's also a RuboCop checker in syntastic.
If you're a ST user you might find the Sublime RuboCop plugin useful.
The brackets-rubocop extension displays RuboCop results in Brackets. It can be installed via the extension manager in Brackets.
The textmate2-rubocop bundle displays formatted RuboCop results in a new window. Installation instructions can be found here.
The atom-lint package runs RuboCop and highlights the offenses in Atom.
The lt-rubocop plugin provides LightTable integration.
Here's one great opportunity to contribute to RuboCop - implement RuboCop integration for your favorite editor.
If you're fond of Guard you might like guard-rubocop. It allows you to automatically check Ruby code style with RuboCop when files are modified.
To use RuboCop in your Rakefile
add the following:
require 'rubocop/rake_task'
Rubocop::RakeTask.new
The above will use default values
require 'rubocop/rake_task'
desc 'Run RuboCop on the lib directory'
Rubocop::RakeTask.new(:rubocop) do |task|
task.patterns = ['lib/**/*.rb']
# only show the files with failures
task.formatters = ['files']
# don't abort rake on failure
task.fail_on_error = false
end
Here's a list of RuboCop's core developers:
Here's a list of all the people who have contributed to the development of RuboCop.
I'm extremely grateful to each and every one of them!
If you'd like to contribute to RuboCop, please take the time to go through our short contribution guidelines.
Converting more of the Ruby Style Guide into RuboCop cops is our top priority right now. Writing a new cop is a great way to dive into RuboCop!
Of course, bug reports and suggestions for improvements are always welcome. GitHub pull requests are even better! :-)
If you're interested in everything regarding RuboCop's development, consider joining its Google Group.
RuboCop's changelog is available here.
Copyright (c) 2012-2014 Bozhidar Batsov. See LICENSE.txt for further details.