【Ruby】GuardとRakeで面倒なものを自動化する

こんにちは、しきゆらです。

今回は、Web開発中によく行うであろう、ローカルサーバに編集したコードをコピーする部分を自動化してみます。

 

おそらく、すべてGuardさんだけで行けるかもしれませんがRakeも使ってみたいので療法を使っていきます。


 

RakeとGuard

Rake

名前から感じ取れるように、makeをRubyで拡張したようなものです。

RakeはGemのコンパイルなどでよく使われますね。

面倒な記号をたくさん使わずに、Rubyで書けるmakeのようなイメージでしょうか。

私は、Makefileを書いたことがないですが、ファイルを除くと見慣れぬ記号がたくさんでよくわからなかった記憶があります。

とにかく、RakeはRubyが書ければ使えるツールです。

タスクを複数定義しておき、コマンドでタスクを実行していきます

例えば、

rake task1

とすると、Rakefileに定義されたtask1というタスクを実行してくれます。

 

Rake自体は、よほど古いRubyを使っている場合を除き、すでにインストールされているはずです。

しかし、今回はGuardをBundleで管理するので改めて追加していきます。

 

Guard

これは、前に書いてますね。

【Ruby】タスクランナーGuardを触ってみる

 

最近流行り(?)のタスクランナーです。

 

前回はJSのGruntやgulpのRuby版、と書いてますが

どうもこの分野はRubyが先行していたようです。

GruntはRubyのGuardをもとにしているともあります。

わかりやすくまとめられているサイトを載せておきます。

ビルドツールまとめ。Gruntとかgulpとか (フロント寄り) – Qiita

 

Rakeも似たようなものですが。ファイルの監視はしてくれません。

Rakeは自分でコマンドを打って実行しなければいけませんが、Guardはファイルを監視してくれるので、裏で勝手に動いてくれます。

 

例えば、SassやCooffeeScriptなどのメタ言語をコンパイルしたいときなどに使えそうですよね。

 

 

今回は、Guardでファイルの更新を監視し、更新があればRakeでファイルのコピーを実行していこうと思います。

 

BundleでRake、Guardを管理

bundle init

とすると、Gemfileが作られるはずです。

以下のようにします。

source "https://rubygems.org"
 
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
 
gem "guard"
gem "guard-shell"
gem "rake"

書き終わったら

bundle install --path vendor/bundle

とすると、インストールできます。

 

ディレクトリ構造

イメージしやすく、以下のような形のものを考えて見てください。

guard_test/
   ├── vendor/bundle
   ├── ruby/
   │   └── server.rb
   ├── js/
   │   └── main.js
   ├── css/
   │   └── main.css
   ├── scss/
   │   └── main.scss
   └── main.html

言語ごとにディレクトリを分けて置いてあるとします。

コピーしたいのはHTML、CSS、JS、Rubyの4種類のファイルであると仮定します。

 

Rakeの初期化

ターミナルから

bundle exec rake init

とするとRakefileが出来るはずです。

これにRakeのタスクを登録していきます。

 

# syncという名前のタスクを定義
task :sync do
  # local_passwdの中身をsudoのパスワードとして実行する
  `cat local_passwd | sudo -S rsync -pr --exclude-from=/.rsync/excludes . /path/to/directory`
end

# Rakeのデフォルトタスク(他言語で言うところのmain関数のようなもの)をsyncに指定
task default: [:sync]

コメントを見ながら読んでもらえれば、わかるかと思います。

今回、私はsudo権限でないと書き込めないところにファイルをコピーしたかったので無理やりこんな感じにしてみました。

sudoのオプションとして「-S」をつけると、ターミナルの出力されたものをパスワードとして使えるようです。

そこで、local_passwdというファイルにパスワードを書いておき、それをcatで読み込みます。

それをパイプでsudo rsyncに送っています。

 

なお、送りたくないファイルの指定もしています。

rsyncの「exclude-from=/path/to/config_file」とオプションを付けると、config_fileに書いてあるファイル・ディレクトリを無視してくれます。

 

念のため、

rake

コマンドを実行して、ファイルがコピーできるかを確認してみてください。

これができれば、Rakeでのタスク定義がおわりです。

 

では次に、Guardのタスクを書いていきましょう。

Guardの初期化

bundle exec guard init

こうすると、Guardfileというファイルができているはずです。

これにGuardタスクを追加して行きます。

# shellという名前のタスクを定義
 guard :shell do
 # js,ruby,css以下のファイルとhtmlファイルを監視
  watch(%r{^(js|ruby|css|[^.!])?\/[\S]+.[\S]|[\S]*.html}) do |m|
    # 更新されたファイル名をTerminalに表示
    puts m[0]
    # rakeコマンドを実行
    `rake sync`
    # Macの画面に更新完了した旨をポップアップ
    `osascript -e 'display notification "rsync done!!" with title "Guard Auto Message"'`
  end
end

こちらも、コメントを見ていただければ何をやっているかはなんとなくわかっていただけるかと思います。

watchの引数に監視したいファイルを正規表現を使って指定します。

今回は、HTML、CSS、JS、Rubyの4種類のファイルをコピーしたいので、これらの更新を監視します。

 

正規表現で指定したものが、本当にあっているかを確認する場合は、「Rubular」というサイトでWeb上で確認できます。

Rubular

「Your regular expression:」のところに、正規表現を書きこみ、「Your test string:」のところに対象となる文字列を書き込みます。

今回は、ファイルパスを対象文字列とするので、画像のように幾つか追加してみました。

きちんと、ほしいのもはマッチしているようです。

 

さて、ここまでで基本的なタスクは設定が終わりました。

ではGuardを実行して見ましょう。

bundle exec guard start

これでGuardがファイルの監視を開始してくれます。

適当なhtml,js,ruby,cssファイルを更新してみてください。

 

Sassのコンパイル

これで一件落着、と思いきや、足りないものがあります。

ディレクトリ構造を見てください。

Sassを使ってCSSを書いているようですね。

 

Sassを書き換えても、CSSにコンパイルしなければCSSファイルは更新されません。

Sassを監視しても良いのですが、CSSにコンパイル=>ファイルコピーという流れになり

ちょっとタスクの流れに分岐ができそうです。

 

そこで、GuardさんはSassのコンパイルも勝手にやってくれるプラグインがあります。

これもGemとして配布されているようなので、Gemfileに追加しましょう

source "https://rubygems.org"
 
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
 
gem "guard"
gem "guard-shell"
gem "rake"
gem "guard-sass" # <= 追加

そして、インストール。

bundle install

最初のインストールのときにパスを指定してあるので、2回目以降はパスを指定しなくても

vendor/bundleに勝手にインストールしてくれます。

 

では、guard-sassの設定をしていきましょう。

 

guard-sassの設定

といっても、これもGuardさんなので、以下のコマンドでおわり。

bundle exec guard init sass

こうすると、Guardfileの最後に「:sass」というタスクが追加されているかと思います。

guard 'sass', input: 'sass', output: 'css'

 

今回は、SCSS形式で書いているようで、ディレクトリ名も「scss」となっています。

そこで、inputをscssに変更します。

guard 'sass', input: 'scss', output: 'css'

 

これで、scssを監視し、cssファイルに出力してくれます。

sassコマンドのwatchのようなイメージでしょうか。

 

では、Guardを一旦止め、もう一度実行してみましょう。

すると、main.scssファイルを変更すると、cssにコンパイルしてくれます。

そうするとcssファイルが更新されてrake syncでファイルをコピーしてくれます。

 

素晴らしいですね。

これで、面倒なファイルコピーを自動化できます。

しかも、処理が終わればMacのポップアップを表示してくれます。

 

Guardさんはあまり情報がなく、ここまでたどり着くのに苦労しました。

そして、正規表現。うごごご・・・

 

今回は、ここまで。

おわり