読者です 読者をやめる 読者になる 読者になる

Rails Webook

自社のECを開発している会社で働いています。Rails情報やサービスを成長させる方法を書いていきます

Railsの開発効率を上げる - guard-rubocopを使ってRailsで自動で静的コード解析ツール(RuboCop)を実行させる

開発を効率化する Rails gem

f:id:nipe880324:20141016010205p:plain:w320

Guardとは

Guardとはファイルの変更を検知して、自動的にさまざまな処理を実行してくれるRubyのGemです。
これ単体で使うよりも、他のツールと連携し、自動的に処理を行い開発効率を上げるために使います。
メジャーどころとしては、次の3つだと思います。


本記事では、Railsへguard-rubocopの導入方法を記載します。
また、rubocopは自動で動くので、失敗したときに、Mac OS X の通知センターの機能を使って通知するようにします。

f:id:nipe880324:20141019145153p:plain:w320

対象読者

  • Railsの開発効率を上げたい方

確認バージョン

  • Mac OSX 10.9
  • Ruby 2.0
  • Rails 4.1
  • guard 2.6.1
  • rubocop 0.26.1
  • guard-rubocop 1.1.0
  • terminal-notifier-guard 1.5.3

目次

  1. Railsプロジェクトの作成
  2. guard-rubocopの導入
  3. guard-rubocopのオプション
  4. guard-rubocopとguard-rspecの混合

1. Railsプロジェクトの作成

まず、Guardを実行させるベースとなるRailsのプロジェクトを作成します。

rails new guard_test

次に、簡単なProductのScaffoldを作成します。

cd guard_test
rails g scaffold Product name:string price:integer discontinued:boolean

マイグレートします。

rake db:migrate

2. guard-rubocopの導入

Gemfiledevelopemntグループ内に必要なgemを追加します。

# Gemfile
group :development do
  gem 'rubocop'
  gem 'guard-rubocop'
  gem 'terminal-notifier-guard'
end

Bundlerを実行して、インストールします。

bundle install

Guard定義が記載されたGuardfile(Guardの設定ファイル)を作成します。

guard init rubocop

コマンドが上手くいかない場合は、下記を実行して下さい。

gem install rubocop
gem install guard-rubocop
gem install terminal-notifier-guard


作成されたGuardfileの中身を確認してみます。
rubocopのブロック内に監視対象が記載されています。
watchメソッドで監視するファイルを正規表現で記載します。

# Guardfile

guard :rubocop do
  watch(%r{.+\.rb$})
  watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
end

次のように修正します。

# Guardfile

# guard :rubocop do
guard :rubocop, all_on_start: false, cli: ['--format', 'clang', '--rails'] do
  watch(%r{.+\.rb$})
  watch(%r{.+\.rake$}) # .rakeファイルも監視対象にする
  watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
end

上記の設定でguard起動時にrubocopを実行させず、失敗時に通知センターに通知がされます。
rubocopの詳細なオプションについては、本記事下記の「guard-rubocopのオプション」を参照して下さい。


では、Guardを実行します。

bundle exec guard

※Railsプロジェクトの配置パスに日本語が入っていると、「E, [2014-10-16T00:43:38.055423 #28197] ERROR -- : run() in thread failed: inspected result must be ASCII only or use the same encoding with default external:/Users/nipe0324/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/listen-2.7.9/lib/listen/listener.rb:329:in `inspect'」のようなエラーが発生するのでご注意ください。

.rbのファイルを編集することで、自動でrubocopが動き、(デフォルトのrubocopの規約が厳しすぎて)失敗するので、右上で通知がされます。

f:id:nipe880324:20141019145153p:plain:w320

これで、自動でrubocopを起動する環境を構築することができました。
rubocopの設定については、bbatsov/rubocop · GitHub を参照して下さい。


3. guard-rubocopのオプション

次のようにguard-rubocopにオプションを指定することが可能です。

# Guardfile

guard :rubocop, all_on_start: false, cli: ['--format', 'clang', '--rails'] do
  watch(%r{.+\.rb$})
  watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
end

指定できるオプションは次のようになっています。

all_on_start: true     # Guard起動時にすべてのファイルをチェックする(デフォルト値:true)
cli: '--rails'         # RuboCopへのオプションをを文字列か配列で指定する(デフォルト値:nil)
keep_failed: true      # Keep failed files until they pass. (default: true)
notification: :failed  # 実行後に通知センターに通知をする(デフォルト値:failed - 失敗時)
                       #   true    - 毎回通知する
                       #   false   - 通知をしない
                       #   :failed - 失敗時のみ通知する

guard-rubocopとguard-rspecの混合

TDDで実装しているときに、RedとGreenの段階では、「RSpecが失敗したら、RuboCopの実行をしない」ように制御したい場合があるかもしれません。
そのようなときに、次のようにGuardfileを修正するとよいです。

# Guardfile

# RSpecが失敗したら、RuboCopをスキップする
group :red_green_refactor, halt_on_fail: true do

  guard :rspec do
    ...
  end

  guard :rubocop do
    ...
  end

end


* 参考文献
- [https://github.com/guard/guard:title]