RuboCop(ルボコップ)とは、Rubyのコードを実行せずに読み、スタイルガイドへの違反やバグの芽を指摘して、多くを自動で直す静的コード解析ツール兼フォーマッタです。名前はRubyとCop(警官)を合わせたものです。2026年10月28日時点の最新版はRubyGemsの配布ページで1.92.1(2026年10月22日公開)、ライセンスはMITです。この記事では1.92.1をRuby 4.0.6上で実際に動かし、出力の読み方、-aと-Aで直る範囲の違い、.rubocop.ymlの設定、Rails 8に標準で入るrubocop-rails-omakaseとの差を実測値で示します。静的解析という手法そのものは静的解析とは?検出できる欠陥と静的解析ツールの選び方で整理しています。
まとめ:RuboCopの要点
- 正体:Ruby専用のLinter兼フォーマッタ。読み方は「ルボコップ」。1.92.1には613個の検査ルール(cop)があり、既定で有効なのは394個。
- 最初の一手:
.ruby-versionかTargetRubyVersionを置いてから実行する。対象のRubyを示すファイルが1つも無いと既定値の「Ruby 2.7として解析」になる。 - 自動修正:
-aは安全と判定された修正だけ、-Aは意味が変わりうる修正も適用する。同じ10行のコードで-aは4件、-Aは7件直した。 - 既存コード:
--auto-gen-configで今の違反を.rubocop_todo.ymlへ退避し、新しいコードから規約を効かせる。 - Rails 7.2以降:標準のrubocop-rails-omakaseは43個のcopしか有効にしない。同じコードで素のRuboCopの6件が0件になるので、バグの芽を拾いたいなら
Lintを足す。
RuboCopの役割:Linterとフォーマッタの兼用
RuboCopは、コミュニティが管理するRubyスタイルガイドを既定の規約として、命名・インデント・書き方・複雑さ・危険な書き方を検査します。Linterとして違反を報告するだけでなく、インデントや引用符のような機械的に直せるものはその場で書き換えます。
動作に必要なRubyは2.7.0以上ですが、解析対象のコードはRuby 2.0以降を指定できます(公式の互換性ページ)。
copと部門(department):1.92.1の613個の内訳
検査ルール1つ1つを「cop」と呼び、Layout/LineLengthのように「部門/名前」で表します。1.92.1でrubocop --show-copsを実行して数えた部門ごとの内訳が次の表です。
| 部門 | cop数 | 見ているもの |
|---|---|---|
| Style | 299 | 書き方の流儀(引用符・条件式など) |
| Lint | 160 | バグの芽(未使用の代入・曖昧な式) |
| Layout | 100 | インデント・空白・行長 |
| Naming | 19 | 変数・メソッド・ファイルの命名 |
| Metrics | 10 | メソッド長・クラス長・複雑度 |
| Gemspec | 10 | gemspecの書き方 |
| Security | 7 | evalやJSON.loadなど危険な呼び出し |
| Bundler | 7 | Gemfileの書き方 |
| Migration | 1 | cop名の移行 |
613個のうち既定で有効(Enabled: true)は394個、新しく追加されて有効化を保留している「pending」が163個、既定で無効が56個です(公式のcop一覧も「613 in RuboCop 1.92.1」)。Metricsの閾値は設計の議論にも使われ、たとえばMetrics/ClassLengthの既定は1クラス100行です。この数字をモデル分割の目安に使う考え方はRailsのFat Model対策|1500行model.rbを分割する4手法と判断基準で扱っています。
RuboCopをインストールして最初の検査を動かす
Bundlerを使うプロジェクトでは、Gemfileの開発・テスト用グループに追加します。require: falseは、アプリの起動時にRuboCopを読み込まないための指定です。
# Gemfile
group :development, :test do
gem "rubocop", require: false
end
bundle installのあと、bundle exec rubocopでプロジェクト全体を、bundle exec rubocop app/modelsのようにパスを渡せばその範囲だけを検査します。チームで使うならGemfile.lockで版を固定し、全員とCIで同じ結果になるようにします。gemの追加と版の固定の仕組みはgemとBundlerの使い方|Bundler 4系で変わったコマンドとGemfileの書き方にまとめています。
実行結果の読み方:C・W・[Correctable]の意味
次の10行をsample.rbとして検査しました(.rubocop.ymlでTargetRubyVersion: 4.0とNewCops: enableを指定)。
class Greeter
def initialize(name)
@name=name
end
def greet
unused = 1
puts "Hello, " + @name
end
end
sample.rb:3:10: C: [Correctable] Layout/SpaceAroundOperators: Surrounding space missing for operator =.
sample.rb:7:5: W: [Correctable] Lint/UselessAssignment: Useless assignment to variable - unused.
sample.rb:8:10: C: [Correctable] Style/StringConcatenation: Prefer string interpolation to string concatenation.
1 file inspected, 6 offenses detected, 5 offenses autocorrectable
1行が1件の違反で、「ファイル:行:列: 重大度: cop名: 説明」の順に並びます。重大度は低い順にinfo・refactor・convention(C)・warning(W)・error(E)・fatal(F)の6段階で、既定値は部門ごとに決まります(公式のcop設定の解説)。この例ではLintの違反がW、ほかがCでした。[Correctable]は自動修正できる違反の印です。既定では、自動修正されずに残った違反が1件でもあると終了コードが1になり、CIはこれで失敗を判定します(閾値は--fail-levelで変えられます)。
対象Rubyの手がかりが無いときのRuby 2.7扱い
.rubocop.ymlも.ruby-versionもGemfile.lockも無いディレクトリでrubocop -Vを実行すると、Ruby 4.0.6の上で動かしていてもanalyzing as Ruby 2.7と表示されました。公式の設定の解説によると、TargetRubyVersionが無いときは*.gemspec・.ruby-version・mise.toml・.tool-versions・Gemfile.lockの順に対象のRubyを探し、どれにも無ければソースの既定値(DEFAULT_VERSION = 2.7)を使います。さらにpendingのcopの「設定してください」という警告が160行以上並び、違反が埋もれます。
.ruby-version(4.0.6など)を置くとanalyzing as Ruby 4.0に切り替わり、pendingの警告はNewCops: enableで消えます。Rubyの現行版とサポート期限はRubyの最新バージョンは4.0.7|4.1.0-preview1の変更点・3系との違い・サポート期限で確認できます。
自動修正の-aと-Aの違い:同じコードでの比較
-aは--autocorrect、-Aは--autocorrect-allの短縮形です。公式の自動修正の解説では、copごとにSafe(設計上、誤検出が起こりうるか)とSafeAutoCorrect(修正がコードの意味を保つか)の2つの属性があり、-aは両方が真のcopの修正だけを当てます。上のsample.rbに両方を実行した結果がこの表です。
| 違反(cop) | -a | -A |
|---|---|---|
| Layout/SpaceAroundOperators | 修正 | 修正 |
| Style/StringLiterals | 修正 | 修正 |
| Lint/UselessAssignment | 修正 | 修正 |
| Lint/Void(連鎖) | 修正 | 修正 |
| Style/StringConcatenation | 残る | 修正 |
| Style/FrozenStringLiteralComment | 残る | 修正 |
| Layout/EmptyLineAfterMagicComment(連鎖) | – | 修正 |
| Style/Documentation | 残る | 残る |
「連鎖」は、1つ直した結果として新しく出た違反です。unused = 1の代入を消すと1だけが残ってLint/Voidになり、-Aが足したマジックコメントの後に空行が無いとLayout/EmptyLineAfterMagicCommentになります。RuboCopはこうした連鎖も同じ実行の中で直します。-aの結果は「4 offenses corrected, 2 more offenses can be corrected with rubocop -A」でした。-Aだけが当てた2件が危ない理由は、--explainで確かめられます。Style/StringConcatenationは「受け手が本当に文字列か保証できない」、Style/FrozenStringLiteralCommentは「マジックコメントを足すと文字列がすべて凍結され、文字列を書き換えている箇所がFrozenErrorになる」と説明されます。-Aの後はテストを通し、差分を読んでからコミットしてください。Style/Documentation(クラスの説明コメント)は人が書くしかありません。
bundle exec rubocop --explain Style/FrozenStringLiteralComment
--explainは1.92.0で入ったオプションで、copの説明・Safeの値・-aと-Aのどちらで直るかを端末に出します。旧表記の--auto-correctは1.30.0で非推奨になり、--autocorrectへ置き換わりました。
.rubocop.ymlでルールを調整する
設定はプロジェクト直下の.rubocop.ymlに書きます。全体の設定はAllCops、個別のcopは名前をキーにします。rubocop --initで空の雛形を作れます。
# .rubocop.yml
AllCops:
TargetRubyVersion: 4.0
NewCops: enable
Exclude:
- "db/schema.rb"
- "vendor/**/*"
Layout/LineLength:
Max: 100
Style/Documentation:
Enabled: false
Layout/LineLengthの既定は120文字です(0.84.0で80から120へ変更)。Max: 120と書いても何も変わらないので、書くのは既定から変えたいときだけです。古い記事にあるMetrics/LineLengthは部門を移った旧名です。
TargetRubyVersionを3.4以上にすると、1.75以降は構文解析にRuby本体と同じPrismを使うparser_prismが既定になります(互換性ページ)。Ruby 3.3以下を対象にした場合は従来のparser gemが既定です。
コメントによる部分的な無効化とdisable-next(1.90以降)
特定の行だけ検査を止めるには、行末に# rubocop:disable Style/StringConcatenationを書きます。次の1文だけ止めたいときは、1.90.0で入ったdisable-nextが使えます。
# rubocop:disable-next Style/StringConcatenation
puts 'Hello, ' + name
ESLintの癖でdisable-next-lineと書くと、RuboCopではLint/CopDirectiveSyntaxの「Malformed directive comment」になり、止めたかった違反も残ります。1.90で入ったStyle/DirectiveScopeは、1文だけをdisableとenableで挟む書き方を指摘します。
既存プロジェクトへの後付け:.rubocop_todo.ymlで段階導入
規模のあるコードに後から入れると初回に数百〜数千件の違反が出て、一度に直すとレビューできない差分になります。公式の手順どおり、まず今の違反を記録して黙らせ、新しいコードから規約を効かせます。
bundle exec rubocop --auto-gen-config
sample.rbで実行すると.rubocop_todo.ymlが作られ、.rubocop.ymlの先頭にinherit_from: .rubocop_todo.ymlが足され、再実行の結果は「no offenses detected」になりました。生成内容は「このcopはこのファイルを除外」という形です。
Lint/UselessAssignment:
Exclude:
- 'sample.rb'
Style/StringLiterals:
EnforcedStyle: double_quotes
注意点が2つあります。1つ目は、Style/StringLiteralsのように流儀を選べるcopでは、ファイルを除外するのではなく既存コードの流儀(ここでは二重引用符)に設定が書き換わることです。チームの規約と違う流儀が固定されていないか、生成直後に読んでください。2つ目は、違反ファイルが--exclude-limitの上限(既定15)を超えたcopはEnabled: falseで丸ごと止まることです。新しいコードでも検査されなくなるため、大きなプロジェクトでは--no-exclude-limitを付けてファイル単位の除外にとどめます。
その後は.rubocop_todo.ymlからcopを1つずつ消し、-aで直してレビューする、を繰り返します。LayoutとStyleの-aで直るものから始めると、意味を保つと判定された修正なのでレビューの負担が比較的軽く済みます。それでもテストは毎回通します。
Rails標準のrubocop-rails-omakaseと素のRuboCopの検査範囲の差
Rails 7.2以降のrails newは、Gemfileの雛形にrubocop-rails-omakaseを入れ、.rubocop.ymlをinherit_gem: { rubocop-rails-omakase: rubocop.yml }の1行で生成します(--skip-rubocopで外せます)。
omakase 1.1.0の設定ファイルを読むと、まず全部門をEnabled: falseにし、そのうえで43個のcopだけを有効にしています。内訳はLayout27個・Style12個・Lint3個・Performance1個です。前述のsample.rbをomakaseの設定で検査した結果がこの表です。
| 設定 | 違反 | 未使用の代入 |
|---|---|---|
| 素のRuboCop(NewCops: enable) | 6件 | 検出 |
| rubocop-rails-omakase | 0件 | 見逃す |
| omakase+Lint: Enabled: true | 1件 | 検出 |
omakaseの有効copは大半がLayoutとStyleで、この例の未使用の代入(Lint/UselessAssignment)は検出されませんでした。Rails部門もプラグインは読み込むものの部門ごと無効です。判断はこうです。DHHの流儀の書式で揃えば十分なチームはomakaseのままでよいです。レビューで機械に拾わせたいのがバグの芽なら、omakaseを継承したうえでLint部門を有効にします。Railsらしい書き方まで強制したいなら、omakaseをやめて素のRuboCopとrubocop-railsの組み合わせに切り替えます。Lintを足すとpendingの警告が再び出るので、NewCopsも決めておきます。
# .rubocop.yml(omakaseにバグの芽の検出を足す)
inherit_gem:
rubocop-rails-omakase: rubocop.yml
AllCops:
NewCops: enable
Lint:
Enabled: true
プラグインでRails・RSpec・性能の規約を足す
Rails・RSpec・性能の規約は別gemのプラグインが担います。1.72でプラグイン機構が入り、設定はplugins:キーで読み込みます(公式の移行ガイド)。
# Gemfile
gem "rubocop-rails", require: false
gem "rubocop-rspec", require: false
gem "rubocop-performance", require: false
# .rubocop.yml
plugins:
- rubocop-rails
- rubocop-rspec
- rubocop-performance
| プラグイン | 対象 | plugins:対応 | 最新版 |
|---|---|---|---|
| rubocop-rails | Railsの書き方 | 2.30.0〜 | 2.38.0 |
| rubocop-rspec | RSpecのテスト | 3.5.0〜 | 3.10.2 |
| rubocop-performance | 遅い書き方 | 1.24.0〜 | 1.27.0 |
最新版は2026年10月28日にRubyGemsで確認した値です。古い書き方のrequire:キーにrubocop-railsを並べても動きますが、1.92.1では「rubocop-rails extension supports plugin, specify plugins: rubocop-rails instead」という警告が出ました。plugins:に対応した版のプラグインなら書き換えておきます。
エディタ・CI・AIエージェントからRuboCopを動かす
サーバーモードによる起動待ちの短縮
RuboCopは起動のたびに設定とプラグインを読み込みます。1.31で入ったサーバーモードは常駐プロセスに検査を任せます。rubocop-railsとrubocop-performanceを読み込んだ状態でsample.rb 1ファイルを検査すると、通常実行は3回とも13秒台、--serverは1回目こそ13.1秒でしたが2回目以降は1.4〜2.0秒でした(キャッシュを切る--cache falseで計測・Intel Core i9-9880H。絶対値はマシンの負荷で変わります)。サーバーを起動していても、--serverを付けないか環境変数RUBOCOP_OPTSに入れない限り、通常のコマンドはサーバーを使いません。
bundle exec rubocop --start-server
bundle exec rubocop --server app/models
bundle exec rubocop --stop-server
エディタ連携:組み込みLSPとRuby LSP
1.53からRuboCop自身がLanguage Serverとして動き、bundle exec rubocop --lspをエディタのLSPクライアントから起動すると、入力中に違反が表示され、保存時に整形できます(公式のLSPの解説)。VS CodeではShopifyのRuby LSP拡張がGemfileにあるRuboCopを自動で使うので、個別の設定はほぼ要りません。拡張の入れ方と整形の設定はruby on rails を vscode で開発する環境構築【2026年版】Ruby LSP・デバッグ・Dev Containerで手順にしています。
GitHub Actionsでのプルリクエスト検査
プッシュとプルリクエストのたびに検査し、違反があればジョブを失敗させます。ruby/setup-rubyはruby-versionを省くと.ruby-versionを読み、bundler-cache: trueでbundle installとgemのキャッシュまで行います。actions/checkoutの現行メジャー版はv7(v7.0.1が2026年7月20日公開)です。
# .github/workflows/rubocop.yml
name: RuboCop
on: [push, pull_request]
jobs:
rubocop:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- run: bundle exec rubocop --format github
--format githubを付けると、違反がプルリクエストの差分の該当行に注釈として表示されます。ワークフローが失敗するだけではマージは止まらないので、ブランチ保護(またはルールセット)でこのジョブを必須のステータスチェックに指定します。CodeRabbitもRuboCopを内部で走らせられるので、CIとの分担はCodeRabbitの導入手順と.coderabbit.yaml設定・料金と分担の決め方を参考に決めます。
MCPサーバー:AIエージェントからの検査と修正
1.85で実験的機能として入ったrubocop --mcpは、検査(rubocop_inspection)と自動修正(rubocop_autocorrection)をAIエージェントのツールとして公開します。公式のMCPの解説のとおりmcp gemは依存に含まれないので別途Gemfileに足します。実験的機能なので、CIの判定には通常のコマンドを使います。
Standard Ruby・Brakemanとの使い分け
Standard Rubyとomakaseは「RuboCopの規約をどう決めるか」の選択肢で、どちらか1つを選びます。Brakemanは守備範囲が違うので併用します。
| ツール | 中身 | 設定の自由度 | 向く場面 |
|---|---|---|---|
| RuboCop | 本体(613cop) | cop単位で全部 | 自分たちの規約を作る |
| Standard Ruby | RuboCopが基盤 | 原則変えない | 規約の議論をやめたい |
| rubocop-rails-omakase | RuboCopの設定集 | 上書き可 | Railsの既定に乗る |
| Brakeman | 別エンジン | 検査の選択・除外 | Railsの脆弱性検出 |
Standard Ruby(最新は1.57.0)はRuboCopを基盤にしたLinter兼フォーマッタで、規約を設定させないことで議論を省きます。規約を自分たちで決めたいならRuboCop、決めたくないならStandardです。ただしRubyGemsの依存情報ではStandard 1.57.0がRuboCopを~> 1.91.0に固定しているため、同じGemfileでRuboCop 1.92系を指定すると依存が解決できません。どちらもSQLインジェクションのような脆弱性は見ないため、RailsアプリならBrakemanを並べます。静的解析が見つけられるバグとテストでしか見つからないバグの境目は、静的テストと動的テストの違い|静的解析・動的解析で見つかるバグを同じコードで比較で同じコードを使って比べています。
よくある質問
RuboCopの読み方は?
「ルボコップ」です。Ruby+Cop(警官)を合わせた名前です。映画のRoboCop(ロボコップ)とは綴りが違います。
rubocop -a と -A の違いは?
-aは意味を保つと判定された修正だけ、-Aは意味が変わりうる修正も当てます。10行の例では-aが4件、-Aが7件直しました。
RuboCopの最新バージョンは?
2026年10月28日時点で1.92.1(2026年10月22日公開)です。2026年は1.91.0が9月10日、1.92.0が10月10日と1か月前後でマイナー版が出ています。公式の版の方針では、新しいcopはマイナー版でpendingとして足され、既定で有効にするのはメジャー版です。
RailsにはRuboCopが最初から入っている?
Rails 7.2以降のrails newではrubocop-rails-omakaseが入り、RuboCop本体もその依存として入ります。ただし有効なcopは43個だけです。
RuboCopは無料で使える?
無料です。MITライセンスで、商用プロジェクトでも使えます。rubocop-rails・rubocop-rspec・rubocop-performanceもMITです。