こころがホッコリー

ただイカしたRubyistになりたい人生だった。

Railsで未使用のメソッド削除を支援するEngine(gem)を作った

はじめに

先日のエントリーで、任意のメソッド呼出を監視し、任意のコードを実行するgem「Okuribito」の作成を報告しました。

muramurasan.hatenablog.jp

OkuribitoはRuby単体で動くgemで、元々は未使用のメソッドを安全に削除することを目的に作成したgemです。
が、大抵はRuby単体ではなく、Railsプロジェクトに適用されることが多いのではないかと思います。
そこで、Okuribitoを利用したRails Engineを作れば、メソッド呼出状況の一覧表示・検索などの機能もWebUIで提供できるのではないかと考え、実際に作成してみました。

github.com

このエントリでは、このRails Engineの紹介および使い方の説明をしたいと思います。

OkuribitoRailsとは

OkuribitoRailsはRailsアプリケーションにおけるメソッド呼出状況を監視し、管理(閲覧)できるようにする Rails Engine(gem) です。
言い換えれば、まだ一度も呼び出されていないメソッドを炙り出すことができ、安全にコードからメソッドを削除できるようになると言えます。

その仕組みを実現するため、コア部分の実装は Okuribito を利用しています。
なお、使い方を簡単に説明すると、次のようになっています。

  1. 監視したいメソッドを登録する(yamlを記述し、配置する)
  2. Railsアプリケーションを起動し、運用する。監視対象のメソッド呼出が行われると、DBに情報が格納される
  3. 現在のメソッド呼出状況、メソッド呼出履歴を閲覧する

ひとたび監視したいメソッドを登録すれば、2はgem側でやってくれるので、開発者は 「監視メソッドの設定 → 呼出状況のチェック」というループに注力することができます。

使い方

以下に、Railsチュートリアルのサンプルアプリにおけるメソッド呼出を監視する、という例を通じて、OkuribitoRailsの使い方を説明していきたいと思います。

インストール

まず、Gemfileに次の記述を追加してbundle installします。

gem 'okuribito_rails'

次に、各種設定ファイル配置・書き換えのためのインストールコマンドを実行します。

rails generate okuribito_rails:install

実行すると、以下のタスクが展開されます。

  • OkuribitoRailsが使うmigrationファイルの配置(db/migrate以下)
  • OkuribitoRailsのルーティング追加(config/routes.rbに自動的に追加される)
  • 設定ファイルの配置(config/initializers/okuribito_rails.rb)

migrationの実行

インストールコマンドで追加された分のmigrationを実行します。

rake db:migrate

監視したいメソッドの記述

監視したいメソッドをyamlファイルに記述していきます。(デフォルトの設定では、config/okuribito.ymlにて配置する必要があります)
以下のように、クラス名にネストしてメソッド名を記述していきます。
メソッド名を記述する際は、クオテーションで囲み、それがクラスメソッドなのかインスタンスメソッドなのかのシンボルを記述する必要があります。

User:
  - '#feed'
  - '#profile'
Micropost:
  - '.from_users_followed_by'

設定ファイルの変更(任意)

config/initializers/okuribito_rails.rbはデフォルトで以下の設定になっているので、必要に応じて変更します。

OkuribitoRails.configure do |config|
  config.setting_path = "config/okuribito.yml"
  config.once_detect = true
  config.prohibit_webui = ["test"]
  config.prohibit_observe = ["test"]
end
  • setting_path
    • 監視したいメソッドを記述したyamlのパスを書きます。
  • once_detect
    • trueにすると、メソッド呼び出し検出時の、呼出履歴の登録をRailsアプリケーション起動中に一度だけにします。(DBへinsertするオーバーヘッドを軽減させることができます)
  • prohibit_webui
    • 配列で指定した環境下で、WebUI(メソッド呼び出し状況の閲覧 等)を一切見れなくします。production環境ではWebUIを閉じたい、といった場合に対応することができます。
  • prohibit_observe
    • 配列で指定した環境下で、メソッド呼び出しの監視をしなくなります。staging環境やtest環境ではメソッド呼び出しの監視をしたくない、といった場合に対応することができます。

運用

OkuribitoRailsをインストールしているRailsアプリケーションは、以下の動作をするようになります。

  1. アプリケーション起動時、yamlファイルに記述した監視メソッドをDBに登録する。
  2. アプリケーション実行中、監視メソッドが呼び出されると、その情報をDBに登録する。

こうして蓄積された情報は、WebUIを通じて、それぞれ以下の通り閲覧することができます。

メソッド呼び出し状況の閲覧

(root)/okuribito_rails/method_call_situations にアクセスすると、以下の通り、現在のメソッド呼び出し状況を閲覧することができます。

f:id:muramurasan:20161211194554p:plain

監視中のメソッド一覧が表示され、監視開始日時と、呼出日時を確認することができます。
この例では、User#profileがまだ呼び出されていないことがわかり、今後も未呼出が続くようであれば、コードからメソッドを削除しても良いだろうと判断するこができます。

メソッド呼び出し履歴の閲覧

(root)/okuribito_rails/method_call_logs にアクセスすると、以下の通り、これまでのメソッド呼出履歴を閲覧することができます。

f:id:muramurasan:20161211194606p:plain

呼び出された日時と、その時に呼び出された箇所が記録されているため、どこのコードがまだメソッドを利用しているのか確認することができます。

課題

最低限の機能は作ることができたと思っていますが、使い勝手を良くするために、今後は以下の機能をリリースしたいと考えています。

  • 検索機能
    • メソッド名や、日時を条件に検索(絞り込み)できるようにする機能の提供。
  • メソッド監視日数の表示
    • メソッドの監視開始から経過した日数を表示・検索できるようにする機能の提供。
  • コード内未定義のメソッドを監視対象から排除
    • 上記の条件で、yamlファイルの内容を書き換えるコマンドの提供。
  • 呼出履歴のあるメソッドを監視対象から排除
    • 上記の条件で、yamlファイルの内容を書き換えるコマンドの提供。

おわりに

今回作ったOkuribitoRailsは、Railsアプリケーションにおけるコード整理を助けるRails Engine(gem)です。
コードが汚いのは、ただただ申し訳なさしかありませんが、機能的には有用なものが作れたのではないかと思っています。
使ってみて、もしもバグと思える動作が発生した際は、(詳細を添えて)是非、issue への登録をお願い致します!(もちろん、要望も歓迎します!)
また、機能やコードを改善するPull Requestもお待ちしています!

少しでも「いいね」と思っていただけた方は、是非、リポジトリにStarをつけていただけると幸いです \(^o^)/