rvm-capistranoを使わずRVM使用のサーバにCapistranoでデプロイする

デプロイ先のRubyがRVMだと、そのままだとRubyCapistranoが見つけてくれないので、うぐっとなります。

しかし、デプロイする側のローカル環境でもRVMを使っている場合には、rvm-capistranoというgemをインストールして使うと、ちょこっと設定を付け足すだけで、うまいこと処理してくれるようになります。


では、デプロイする側にRVMが入ってなかった場合はどうするのかというと、deploy.rbに:default_environmentを設定してやればOKです。

自分の場合はこのようにしました。

#deploy.rb
#remote rvm path
set :rvm_base_path, "/home/deploy_user/.rvm"
set :rvm_rb_version, "ruby-1.9.3-p194"
set :rvm_rb_path, rvm_base_path+"/gems/"+rvm_rb_version
set :default_environment, {
  'PATH' => "#{rvm_rb_path}/bin:#{rvm_rb_path}@global/bin:#{rvm_base_path}/rubies/#{rvm_rb_version}/bin:$PATH",
  'GEM_HOME' => rvm_rb_path,
  'GEM_PATH' => "#{rvm_rb_path}:#{rvm_rb_path}@global",
  'BUNDLE_PATH' => "#{rvm_rb_path}/bin"
}

重複部分を変数にまとめました。
各PATHの実際の値は、デプロイ先のサーバーに、デプロイするユーザーで入って、rvm infoして出てきた値を記述してます。
BUNDLE_PATHはwhich bundleして確認しました。


開発側が、rbenvとRVMをばらばらに使ってたのでこんな話になりました。

twitter-bootstrap-railsを使ったRailsアプリをサブディレクトリ運用のPassengerにデプロイしたらAsset Pipelineでハマった

twitter-bootstrap-railsは便利ですね。

とてもナイスなわけですが、タイトルの通り、PassengerでRailsをサブディレクトリで配備してたら、Asset Pipelineでハマったのでメモ。


先にどうしたかだけ書いておくと、Webフォントでの表示はやめて、画像表示にしました。


何がハマったのかというと、Twitter Bootstrapのアイコンを使ってゴミ箱とかユーザーとか表示をしてました。

ソース見てみると、Webフォントを使って表示してるんですね。ちょっと前までは画像だけしか使ってなかったと思ったのですけど。

で、開発環境では表示されていたのですが、Capistranoで本番環境にデプロイしたら表示されなくなったと。


本番環境はPassengerで、Virtual Hostを使用せずに、サブディレクトリで運用してます。

#passenger.conf
RailsBaseURI /railsapp1

なので、URLはexample.com/railsapp1/となるわけです。

Webフォントやアイコンが参照するURLがCSS上でどうなっているのか、実際にprecompileされたCSSを調べてみると、/assets/fontawesome-webfont.eot*1とか、/assets/twitter/bootstrap/glyphicons-halflings.pngとかなっていて、example.com/assets/fontawesome-webfont.eotとなり、railsapp1が抜けているので404になってました。


ならばと、bootstrap_overrides.css.lessの該当箇所を相対パスに変更してみました。

//@iconSpritePath: asset-path('twitter/bootstrap/glyphicons-halflings.png');
//@iconWhiteSpritePath: asset-path('twitter/bootstrap/glyphicons-halflings-white.png');
@iconSpritePath: './twitter/bootstrap/glyphicons-halflings.png';
@iconWhiteSpritePath: './twitter/bootstrap/glyphicons-halflings-white.png';

// Set the Font Awesome (Font Awesome is default. You can disable by commenting below lines)
// Note: If you use asset_path() here, your compiled boostrap_and_overrides.css will not 
//       have the proper paths. So for now we use the absolute path.
//@fontAwesomeEotPath: '/assets/fontawesome-webfont.eot';
//@fontAwesomeWoffPath: '/assets/fontawesome-webfont.woff';
//@fontAwesomeTtfPath: '/assets/fontawesome-webfont.ttf';
//@fontAwesomeSvgPath: '/assets/fontawesome-webfont.svg';
@fontAwesomeEotPath: './fontawesome-webfont.eot';
@fontAwesomeWoffPath: './fontawesome-webfont.woff';
@fontAwesomeTtfPath: './fontawesome-webfont.ttf';
@fontAwesomeSvgPath: './fontawesome-webfont.svg';

// Font Awesome
@import "fontawesome";

開発環境では、両方表示されていたので*2、本番環境にアップしてみたところ・・・

@font-face{font-family:'FontAwesome';
src:url(/assets/./fontawesome-webfont-7cf1b0de49e2f8672c9ad6d9e382115f.eot);
src:url(/assets/./fontawesome-webfont.eot?#iefix) format("embedded-opentype"),url(/assets/./fontawesome-webfont-9c0e35b95bf9cea29c77678ebf71a29d.woff) format("woff"),url(/assets/./fontawesome-webfont-1e29be0bb354c9f664cbca7df9a966d8.ttf) format("truetype"),url(/assets/./fontawesome-webfont.svg#FontAwesome) format("svg");
font-weight:normal;font-style:normal}

フォントのurl部分には/assets/が差し込まれてしまいました。

画像については、/assets/が入って来なかったので、Webフォント部分をコメントアウトして、画像でアイコンを表示するようにしました。


ちなみに、asset-pathや、bootstrap_twitter-overrides.css.less.erbにして、asset_path等も試してみましたが、本番環境では結局/assets/....となってしまい、サブディレクトリが入らずダメでした。


サブディレクトリではなく、素直にVirtual Hostで運用しとけば起きない問題ではありますね。
Asset Pipelineは便利なんでしょうけど、ハマると面倒です。
以上。


追記:twitter-bootstrap-railsにはstaticブランチという静的なJS,CSSのものがあるのですが、こちらはWebフォント使ってない版でした。

*1:後ろの数字省略

*2:この時点でURLを確認してみればよかったのですが、怠りました

Asset PipelineでController毎のJavaScriptを出力

Rails 3.1以降。


コントローラーを生成すると、app/assets/javascripts/controller_name.js.cofeeが生成されているけど、標準だと、production環境では、どのコントローラーのviewを表示しているかに関係なく、これが全部まとめられてapplication.jsになって出力されている。
development環境の場合も、application.jsにまとめられていないだけで、全ファイルが出力されてる。

下記をfalseにすれば、development環境でもapplication.jsにまとめられて出力される挙動を見られる。

#config/development.rb
config.assets.debug = true

The Asset Pipeline — Ruby on Rails Guidesを読んでみました。

下記2箇所を修正すればOK

#app/assets/javascripts/application.js
//= require_tree .  <-app/assets/javascripts/にあるものを読み込んでしまうので削除
#app/views/layout/application.html.erb
<%= javascript_include_tag "application" %>
<%= javascript_include_tag params[:controller] %>  #<- これを追加

もっと細かく制御したければcontent_forなどを使って出力すれば良いかと。

CSSも同じような感じで。

CapistranoでのRailsデプロイでハマった場合の対処

  • config/deploy.rbを確認
  • capistranoが出しているエラーメッセージをよく見る。
  • ヘルプや公式のリファレンスをよく見る。cap --helpとか
  • cap -Tしてみて、もっとプリミティブなタスクがないか確認してみる
  • cap -e TASK_NAMEも確認してみる
  • cap shellを使って、実際の作業を一つ一つ実行してみる
  • サーバーにsshして、実際にコマンドを打ってみる。環境変数を確認してみる
  • cap shellでコケた手前まで入力してみて、コケたコマンドをサーバにsshして入力してみる
  • gitやsshの設定を見直す。秘密鍵とか。
  • deploy.rbの設定を見直す場合、一気に変えず、1つずつ変えて、挙動をみてみる
  • 本番環境の配備場所を削除して、cap deploy:setupから

ポイントとしてはこんな所かと。闇雲にググって、適当に設定を付け足したり削ったりすると、さらに大ハマリします。
deploy:setupやdeploy:checkがなんか設定いじって通った→deploy:coldやdeployで通らず設定をいじりまくる。とかやると、deploy:setupやdeploy:checkが、どの状態で通ったのかも担保できなくなっちゃいます。
よしんば、まぐれでデプロイ出来る状態になっても、なんでできているのか把握できなくて、後で苦労します。

rspec-railsをGemfileに追加するときにgroupに:developmentを忘れるとrake -Tに出てこず、rake specができなくなる

タイトル通り。

rspec-railsだけ追加してた時は、:developementもついてたんですけど、timecopやcapybaraを追加したときにgroupのブロック内にまとめました。
その時にうっかり外してしまい、出てこなくて数分悩みました。

group :test do
  gem "rspec-rails", :group => :development #<-これを付け忘れ
  gem "timecop"
  gem "capybara"
end

8/1朝活&オープンアワーresult

黙々と作業。
今日も、Railsのテスト周りを中心に。主にはRequest SpecとCapybaraを使用して、エンドツーエンドテストを書いてました。
JavaScriptを少々、Railsアプリのリファクタリングを少々。

以上。