Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

RuboCopを使用したRubyコードのリンティングと自動フォーマット

リンティングは、プログラムおよびスタイルのエラーについてソースコードを自動チェックすることです。このチェックは、リンターと呼ばれる静的コード分析ツールによって実行されます。ただし、コードフォーマッタは、事前に構成された一連のルールに厳密に準拠するようにソースコードをフォーマットするためのツールです。リンターは通常違反を報告しますが、問題を修正するのは通常プログラマー次第ですが、コードフォーマッターはそのルールをソースコードに直接適用する傾向があるため、フォーマットの間違いを自動的に修正します。

プロジェクトでより一貫性のあるコードスタイルを作成するタスクでは、通常、個別のリンティングツールとフォーマットツールを導入する必要がありますが、場合によっては、1つのツールで両方の問題に対処できます。後者の良い例はRuboCopです。これは、この記事で詳しく検討するツールです。 Rubyプロジェクトでセットアップし、出力が期待どおりになるように構成オプションを調整する方法を学習します。ローカル開発プロセスに統合するだけでなく、継続的インテグレーションワークフローの一部にする方法も学習します。

RuboCopのインストール

RuboCopのインストールはRubyGemsを介して簡単です:

$ gem install rubocop

インストールされたバージョンを確認してください:

$ rubocop --version
1.18.3

Bundlerを使用する場合は、以下のスニペットをGemfileに配置してください。 次に、bundle installを実行します 。 require: false 一部はBundler.requireに通知します コマンドラインからのみ使用されるため、コードでその特定のgemを必要としないでください。

gem 'rubocop', require: false

インストールされたバージョンを確認してください:

$ bundle exec rubocop --version
1.18.3

RuboCopの実行

rubocopと入力すると、プロジェクトのデフォルト設定を使用してRuboCopを実行できます。 (またはbundle exec rubocop Bundlerと一緒にインストールされている場合)。コマンドに引数を渡さない場合、現在のディレクトリ内のすべてのRubyソースファイルとすべてのサブディレクトリがチェックされます。または、分析する必要のあるファイルとディレクトリのリストを渡すこともできます。

$ bundle exec rubocop
$ bundle exec rubocop src/lib

構成がない場合、RuboCopは、コミュニティ主導のRubyスタイルガイドで概説されているガイドラインの多くを適用します。コマンドを実行した後、いくつかのエラー(違反)が発生する場合があります。報告された各違反には、違反の説明、発生したファイルと行番号など、問題を解決するために必要なすべての情報が記載されています。

RuboCopを使用したRubyコードのリンティングと自動フォーマット

レポートの下部に、検査されたファイルの数、違反の総数、および自動的に修正できる違反の数を説明する行が表示されます。 -aを追加した場合 または--auto-correct 引数として、RuboCopは、ソースファイル(接頭辞[Correctable]が付いている問題)で見つかった問題を自動的に修正しようとします。 。

$ bundle exec rubocop -a

RuboCopを使用したRubyコードのリンティングと自動フォーマット

修正された各オフェンスのプレフィックスが[Corrected]になっていることに注目してください。 。修正された違反の数の要約もレポートの下部に表示されます。上記の例では、-aを追加した後でも、自動修正されなかった別の修正可能な違反があります。 国旗。これは、一部の自動修正によってコードのセマンティクスがわずかに変更される可能性があるため、RuboCopはそれを安全でないと見なしているためです。これらの違反も自動修正する場合は、-Aを使用してください または--auto-correct-all フラグ。

$ bundle exec rubocop -A

RuboCopを使用したRubyコードのリンティングと自動フォーマット

従うべき経験則は、オートコレクト機能を使用した後にテストスイートを実行して、コードの動作が予期せず変更されていないことを確認することです。

RuboCopの構成

RuboCopは、.rubocop.ymlを介して構成できます プロジェクトのルートに配置されたファイル。すべてのプロジェクトに同じチェックを使用する場合は、グローバル構成ファイルをホームディレクトリ(~/.rubocop.yml)に配置できます。 )またはXDG構成ディレクトリ(~/.config/rubocop/config.yml )。このグローバル構成ファイルは、ローカルスコープのプロジェクト構成ファイルが現在のディレクトリまたは後続の親ディレクトリに見つからない場合に使用されます。

RuboCopのデフォルト構成は、その構成ホームディレクトリ(~/.config/rubocop/default.yml)に配置されます。 )、および他のすべての構成ファイルはそれを継承します。これは、プロジェクト構成をセットアップするときに、デフォルトとは異なる変更を加えるだけでよいことを意味します。これは、特定のチェックを有効または無効にしたり、パラメータを受け入れる場合はその動作を変更したりすることを意味する場合があります。

RuboCopは、個々のチェックを警官と呼び、それぞれが特定の違反を検出する責任があります。利用可能な警官も次の部門にグループ化されています:

  • スタイル警官は主に前述のRubyスタイルガイドに基づいており、コードの整合性をチェックします。
  • レイアウト警官は、空白の使用など、フォーマットに関連する問題をキャッチします。
  • Lint警官は、ruby -wと同様に、コードで発生する可能性のあるエラーを検出します 、ただし、追加のチェックが多数あります。
  • メートル法の警官は、クラスの長さやメソッドの長さなど、ソースコードの測定に関連する問題を扱います。
  • ネーミング警官はネーミング規則に関係しています。
  • セキュリティ警官は、潜在的なセキュリティ問題を見つけるのに役立ちます。
  • Bundlerの警官は、Bundlerファイル(Gemfileなど)の不正行為をチェックします 。
  • Gemspecの警官は.gemspecで悪い習慣をチェックします ファイル。

追加のリンターとフォーマッターを介してRuboCopを拡張することも可能です。独自の拡張機能を構築することも、プロジェクトに関連する場合は既存の拡張機能を利用することもできます。たとえば、Rails拡張機能は、Railsのベストプラクティスとコーディング規則を適用する目的で使用できます。

RuboCopを使用したRubyコードのリンティングと自動フォーマット

初めて構成ファイルを作成すると、追加されたが構成されていない新しい警官の存在を警告する多数のメッセージが表示されます。これは、RuboCopがリリースごとに新しい警官を追加し、ユーザー設定で明示的に有効または無効になるまで、これらが特別な保留状態に設定されるためです。メッセージにリストされている各警官を個別に有効または無効にするか、以下のスニペットを使用してすべての新しい警官を有効にすることができます(推奨)。その後、メッセージは抑制されます。

# .rubocop.yml
AllCops:
  NewCops: enable

構成ファイルやRuboCopが提供する豊富なオプションをいじりたくない場合は、Standardプロジェクトを検討することを検討してください。これは主に、RuboCopの事前構成されたバージョンであり、ルールをカスタマイズすることなく、Rubyプロジェクトに一貫したスタイルを適用することを目的としています。最初に発表されたライトニングトークでは、その起源と動機について詳しく説明しています。

Gemfileに次の行を追加することでインストールできます 次に、bundle installを実行します 。

# Gemfile
gem "standard", group: [:development, :test]

その後、次のようにコマンドラインからStandardを実行できます。

$ bundle exec standardrb
既存のプロジェクトへのRuboCopの追加

ほとんどのRubyistには、グリーンフィールドプロジェクトに取り組む余裕がありません。私たちの開発時間の多くは、すぐに対処できない圧倒的な量のリンティングオフェンスを生み出す可能性のあるレガシーコードベースに費やされています。幸い、RuboCopには、既存の違反の許可リストを生成する便利な機能があり、時間の経過とともにゆっくりと対処できます。利点は、管理不能なリンティングエラーの山に襲われることなく、既存のプロジェクトにリンティングを導入できると同時に、今後の新しい違反にフラグを立てることができることです。

$ bundle exec rubocop

523 files inspected, 1018 offenses detected

許可リスト構成ファイルの作成は、以下のコマンドを使用して実行できます。

$ bundle exec rubocop --auto-gen-config
Added inheritance from `.rubocop_todo.yml` in `.rubocop.yml`.
Created .rubocop_todo.yml.

--auto-gen-config オプションは、すべての違反とそのカウントを収集し、.rubocop_todo.ymlを生成します 現在のすべての違反が無視される現在のディレクトリ内のファイル。最後に、.rubocop.ymlが発生します .rubocop_todo.ymlから継承します コードベースでRuboCopをもう一度実行しても、問題が発生しないようにファイルを作成してください。

$ bundle exec rubocop
523 files inspected, no offenses detected

許可リストファイルの生成中に、違反の数が特定のしきい値(デフォルトでは15)を超えると、RuboCopは警官を完全にオフにします。これは、既存の違反の数が原因で新しいコードがその警官に対してチェックされるのを防ぐため、通常は希望するものではありません。幸い、違反の数が多い場合でも警官が無効にならないように、しきい値を上げることができます。

$ bundle exec rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 10000

--auto-gen-only-exclude オプションは、許可リスト内の各警官がExcludeを持つことを保証します Maxではなく、違反が発生したすべてのファイルを一覧表示するブロック 、警官の除外ファイルの最大数を設定します。 --exclude-limitの設定 Excludeに追加できるファイルの最大数も変更します 各警官のブロック。調査対象のファイルの総数よりも大きい任意の数を指定すると、警官が完全に無効になることはなく、既存または新しいファイルに追加された新しいコードはそれに応じてチェックされます。

既存の違反の修正

.rubocop_todo.ymlを生成した後 ファイルでは、既存の違反を忘れないで、次々とゆっくりと対処することが重要です。これを行うには、Excludeからファイルを削除します 警官をブロックし、報告された違反を修正し、バグの導入を回避するためにテストスイートを実行し、コミットします。警官からすべてのファイルを削除したら、ファイルから警官を手動で削除するか、許可リストファイルをもう一度再生成できます。 --auto-correctを利用することを忘れないでください 可能な場合は、プロセスをはるかに高速化するオプション。

スタイルガイドの採用

RuboCopは非常に構成可能であるため、あらゆるタイプのプロジェクトで実行可能です。ただし、特にデフォルトのルールの多くに同意しない場合は、要件に合わせてルールを構成するのに長い時間がかかる場合があります。このような状況では、既存のスタイルガイドを採用することが有益な場合があります。 ShopifyやAirbnbなど、いくつかの企業がすでにRubyスタイルガイドを公開しています。 RuboCopで好みのスタイルガイドを利用するには、関連するgemをGemfileに追加します。 :

# Gemfile
gem "rubocop-shopify", require: false

次に、プロジェクト構成でそれを要求します:

# .rubocop.yml
inherit_gem:
  rubocop-shopify: rubocop.yml
リンティングエラーの抑制

RuboCopは優れたツールですが、誤検知が発生したり、プログラマーの意図に反する方法でコードを修正することを提案したりする可能性があります。このような状況が発生した場合は、ソースコードにコメントを付けて違反を無視できます。以下に示すように、無効にする個々の警官または部門について言及することができます。

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

または、コードのセクションのすべての警官を一挙に無効にすることができます:

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

行末コメントを使用すると、指定された警官はその行だけで無効になります。

for x in (0..10) # rubocop:disable Style/For
編集者の統合

毎回コマンドラインからチェックを実行する代わりに、エディターにコードを入力するときにRuboCopによって生成される警告とエラーを表示すると便利です。ありがたいことに、RuboCop統合は、ほとんどの一般的なコードエディターとIDEで、主にサードパーティのプラグインを介して利用できます。 Visual Studio Codeでは、このRuby拡張機能をインストールし、ユーザーのsettings.jsonに以下を配置するだけです。 ファイル:

{
  "ruby.lint": {
    "rubocop": true
  }
}

VimまたはNeovimを使用している場合は、coc.nvimを介してRuboCopの診断を表示できます。 Solargraph言語サーバーをインストールする必要があります(gem install solargraph )、続いてcoc-solargraph拡張機能(:CocInstall coc-solargraph )。その後、coc-settings.jsonを構成します 以下に示すようなファイル:

{
  "coc.preferences.formatOnSaveFiletypes": ["ruby"],
  "solargraph.autoformat": true,
  "solargraph.diagnostics": true,
  "solargraph.formatting": true
}

RuboCopを使用したRubyコードのリンティングと自動フォーマット

プレコミットフックの設定

プロジェクト内のすべてのRubyコードが、ソース管理にチェックインされる前に適切にリントおよびフォーマットされていることを確認する優れた方法は、ステージングされた各ファイルでRuboCopを実行するGitpre-commitフックを設定することです。この記事では、Gitの事前コミットフックを管理および構成するためのツールであるOvercommitを使用してセットアップする方法を説明しますが、既存の事前コミットワークフローがある場合は、RuboCopを他のツールと統合することもできます。

まず、RubyGemsを介してOvercommitをインストールしてから、プロジェクトにインストールします。

$ gem install overcommit
$ overcommit --install # at the root of your project

上記の2番目のコマンドは、リポジトリ固有の設定ファイル(.overcommit.yml)を作成します )現在のディレクトリにあり、既存のフックをバックアップします。このファイルはデフォルト構成を拡張するため、デフォルトに関して構成を指定するだけで済みます。たとえば、次のスニペットを使用してRuboCoppre-commitフックを有効にすることができます。

# .overcommit.yml
PreCommit:
  RuboCop:
    enabled: true
    on_warn: fail
    problem_on_unmodified_line: ignore
    command: ['bundle', 'exec', 'rubocop']

on_warn: fail 設定すると、Overcommitは警告を失敗として扱いますが、problem_on_unmodified_line: ignore ステージングされなかった行の警告とエラーが無視される原因になります。プロジェクトのGitHubページで、使用可能なすべてのフックオプションとそれらの許容値の範囲を参照できます。 overcommit --signを実行する必要がある場合があります 構成ファイルを変更して変更を有効にした後。

RuboCopを使用したRubyコードのリンティングと自動フォーマット

場合によっては、すべてのチェックに合格しないファイル(進行中の作業など)をコミットする場合は、ケースバイケースで個々のチェックをスキップできます。

$ SKIP=RuboCop git commit -m "WIP: Unfinished work"

RuboCopをCIワークフローに追加する

プルリクエストごとにRuboCopチェックを実行することは、不適切な形式のコードがプロジェクトにマージされるのを防ぐもう1つの方法です。どのCIツールでも設定できますが、この記事では、GitHubアクションを介してRuboCopを実行する方法についてのみ説明します。

最初のステップは、.github/workflowsを作成することです プロジェクトのルートにあるディレクトリとrubocop.yml 新しいディレクトリ内のファイル。エディターでファイルを開き、次のように更新します。

# .github/workflows/rubocop.yml
name: Lint code with RuboCop

on: [push, pull_request]

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [macos-latest, ubuntu-latest, windows-latest]

    steps:
    - uses: actions/checkout@v2

    - name: Setup Ruby
      uses: ruby/setup-ruby@v1
      with:
        ruby-version: '3.0'
        bundler-cache: true

    - name: Run RuboCop
      run: bundle exec rubocop

上記のワークフローファイルは、コードがGitHubにプッシュされたとき、または任意のブランチに対してプルリクエストが行われたときに実行される単一のジョブを記述しています。 job 順番に実行される一連のステップです。この特定のジョブは、GitHub Actionsによって提供される最新のUbuntu、MacOS、およびWindowsバージョン(runs-onで定義)で1回実行されます。 およびstrategy.matrix )。最初のステップはリポジトリ内のコードをチェックアウトし、次のステップはRubyツールチェーンと依存関係を設定し、最後のステップはRuboCopを実行します。

ファイルの編集が完了したら、ファイルを保存してコミットし、GitHubにプッシュします。その後、後続のチェックインとプルリクエストで報告された問題がインラインで表示されます。

RuboCopを使用したRubyコードのリンティングと自動フォーマット

代替自動フォーマッター

RuboCopは包括的な自動フォーマット機能を提供しますが、ニーズを十分に満たしていない場合に備えて、代替ツールに注意することも重要です。

きれい

Prettierは、JavaScriptの独創的なコードフォーマッターとしてスタートしましたが、現在はRubyを含む他の多くの言語をサポートしています。 Rubyプラグインのインストールは簡単です。prettierを追加してください Gemfileへのgem 次に、bundleを実行します 。

# Gemfile
gem 'prettier'

この時点で、次のコマンドを使用してRubyコードをPrettierでフォーマットできます。

$ bundle exec rbprettier --write '**/*.rb'

Prettierのルールの一部はRuboCopのルールと競合するため、Prettierに干渉しないように、後者のフォーマットチェックを無効にする必要があります。幸い、Prettierと競合する、または不要なRuboCopチェックをオフにするのは簡単です。プロジェクトの.rubocop.ymlの上部にあるPrettierのRuboCop構成を継承するだけです。 ファイル:

# .rubocop.yml
inherit_gem:
  prettier: rubocop.yml

RuboCopを実行する場合(bundle exec rubocop )今後、レイアウトに関連する違反は報告されず、Prettierが独自のルールに従ってそれらを修正するための道が開かれます。 Prettierの出力は、同じプロジェクト内のJavaScriptコードとRubyコードの間で共有できる構成ファイルを介して構成することもできます。

RubyFmt

RubyFmtは、Rustで記述され、現在活発に開発されている新しいコードフォーマッターです。 Prettierと同様に、コード分析ツールではなく、フォーマッターとして使用することを目的としています。まだ安定したリリースが見られていないので、今は採用を控えるべきでしょうが、それは間違いなく注目すべきものです。

結論

コードのリンティングと自動フォーマットは、特に開発者のチームのコンテキストでは、コードベースに非常に多くの利点をもたらします。コードのフォーマット方法を教えられたくない場合でも、リンティングは自分だけのものではないことを覚えておく必要があります。また、共同作業を行う他の人々も同じ規則に従うことができるため、同じプロジェクトで複数のコーディングスタイルを扱うことの欠点がなくなります。

リンターの出力を福音として扱わないことも重要です。そのため、主な目的を損なうことなく、最もメリットが得られるように構成するようにしてください。 RuboCopの広範な構成設定により、これは問題にはなりません。ただし、RuboCopの構成に時間がかかりすぎる場合は、前述のように事前定義されたスタイルガイドを使用するか、詳細を気にすることなく誰もが使用できる構成なしの代替手段としてStandardを採用できます。 。

読んでくれてありがとう、そして幸せなコーディング!


  1. Rubyでの静的分析

    ソースコードを解析して、すべてのメソッド、それらが定義されている場所、およびそれらが取る引数を見つけたいとします。 どうすればこれができますか? あなたの最初のアイデアはそれのために正規表現を書くことかもしれません… しかし、もっと良い方法はありますか? はい! 静的分析 は、ソースコード自体から情報を抽出する必要がある場合に使用できる手法です。 これは、ソースコードをトークンに変換する(解析する)ことによって行われます。 さっそく始めましょう! パーサージェムの使用 Rubyには標準ライブラリで利用可能なパーサーがあります。名前はRipperです。出力を操作するのは難し

  2. iPad と iPhone で QR コードをスキャンする方法

    2018 年の初めに、技術大手の Apple が展開した驚くべき機能は iOS 12 です。iPad と電話で QR コードをスキャンすることは、Apple のユーザー エクスペリエンスを次のレベルに引き上げるために追加された機能の 1 つです。この機能は、生活を楽にするだけでなく、チケット、クーポン、製品の成分などに関する情報を取得するのにも役立ちます。さらに、スマートフォンの助けを借りて QR コードをスキャンできる固有の QR コード認識が付属しています。無意味にカメラ。 QR コードをスキャンすることで、購入前に商品に関する情報を数秒以内に収集できます。 この投稿では、iPad