Drowsy Dog's Diary

any note, any thought

2014年2月4日
by kazoo
0 comments

[rails]アセットパイプラインのためのApache最適化設定

アセットパイプライン

「アセット」とは Web サーバ上の静的コンテンツのこと。具体的には、画像、CSS、Javascript などのファイル。

アセットパイプラインはバージョン3.1以降の Rails に備わっている機能で、主な役目はアセットを圧縮・結合すること、そしてファイルのフィンガープリントをファイル名に組込むこと。この2つの操作を「コンパイル」と呼んでいる。

は、アセットをコンパイルするコマンド。
app/assets/images/
app/assets/stylesheets/
app/assets/javascripts/
app/assets/fonts/

などにあるファイルが「プリコンパイル」される。

コンパイルによって、 app/assets/images/ 以下の画像ファイルには MD5 ハッシュをファイル名に付加して /public/assets/ にコピー。また CSS/JS は、それぞれの拡張子(.scss, .erb, .coffee など)に応じた方法でファイルが変換され、CSS や JS ごとの結合が行われた後、Minification(空白、改行、コメントの除去等)された後に gzip 圧縮される。

このようにすることで、アセットの通信量を最小化しつつ、ファイルの中身の変化に応じてファイル名自体が変わるので、ブラウザやプロキシサーバにキャッシュされていても古いファイルが替わらないという問題を避けられる。むしろ /assets/ 以下の URI へのアクセスに関しては、出来る限りキャッシュを推奨するのが望ましい。そのための HTTP リクエスト/レスポンスのヘッダ設定が以下のようになる。

キャッシュ設定

ここでは CentOS 想定。設定ファイルパス、URI は適当に読み替えてください。

/etc/httpd/sites-available/my_site

それぞれの意味はこんな感じ。

  • ExpiresActive… On にすると Expires および Cache-Control ヘッダを生成する
  • ExpiresDefault… Expires に設定するデフォルトの値。ここではアクセス日時+30日間
  • Header set Cache-Control… HTTP ヘッダの Cache-Control の値を上書きする。”public” は、ブラウザだけでなく Web プロクシにもキャッシュを許可する
  • Header unset Etag… HTTP ヘッダの ETag を削除する(レスポンスが ETag ヘッダを持たないようにする

圧縮設定

アセットパイプラインにおける CSS ファイルなどは圧縮・結合された上で /public/assets/ に配置される。そのとき、*.css, *.css.gz の2つのファイルが生成される。ミニフィケーションと結合だけが行われたものと、それをさらに gzip したもの。

現在多くの Web ブラウザでは、gzip形式で圧縮されたコンテンツをサーバから受け取って、それを展開してからレンダリングする機能を持っている。そういったブラウザは、Accept-Encoding リクエストヘッダに gzip あるいは x-gzip という文字を含む値をセットする。これを受け取った Apache や Nginx といった Web サーバは、その場でコンテンツを圧縮して送り返す。

しかし、アセットパイプラインを利用している場合はすでに圧縮されたファイルが存在しているので、この圧縮は CPU の無駄となる。なので、すでに圧縮済みのファイルを利用するような設定が以下となる。

/etc/httpd/sites-available/my_site

  • AddEncoding… 拡張子 .gz のファイルのエンコーディングが x-zip だと指定する。
  • Header set Vary Accept-Encodig… Vary ヘッダは、リクエストのヘッダによってレスポンスが変化することと、その基準となるリクエストヘッダを Web プロクシに教える。これによってたとえば gzip 圧縮に対応しているブラウザとしていないブラウザが同一のプロクシにアクセスしても問題が出ないようにできる
  • RewriteEngine on/RewriteCond… Accept-Encodingヘッダに gzip/x-gzip という文字を含むリクエストで、かつ末尾に .gz を加えた URI に対応するファイルが存在する場合、それを返す
  • <FilesMatch>…. 拡張子 .css.gz および .js.gz の MIME タイプを ForceType ディレクティブによって指定する

2013年9月3日
by kazoo
0 comments

[rails] ActiveSupport::CoreExtenstions::Hash::Slice

めもん。

Rails の Core Ext の Hash#slice は、引数で与えられた key だけの Hash を返す。
Controller で Request params に対して 有効なキーのみ残したいときなどに使う。

slice! は逆に、引数に与えられたキーを削除して、残された Hash を返す。

参考(v4.0):
http://railsdoc.eiel.info/active_support/core_ext/hash/#slice

ソース(3.2):
https://github.com/kazoo/rails/blob/3-2-stable/activesupport/lib/active_support/core_ext/hash/slice.rb

2013年9月1日
by kazoo
0 comments

【危険】jpoz/APNSの現バージョンにpush通知大量爆撃のバグ

たとえば iOS アプリのサーバサイドを Rails で実装している場合などに PUSH 通知を使いたいとき、
APNs(Apple Push Notification service) 通信用の ruby 実装として便利な gem、jpoz/APNS なのですが、現行バージョン(1.0.0)にかなり危険なバグがあるようで。

https://github.com/jpoz/APNS/issues/19
https://github.com/jpoz/APNS/pull/22

このコミット以来、

と、ループが二重になっていて、たとえば send_notifications に100件のデバイストークンを渡したら、
100人に 1件ずつ PUSH 通知を送っているつもりが、100 人に 100 件ずつ絨毯爆撃されてしまうという状態。。

8/27 に修正もコミットされているのですが、まだ本線にはマージされておらず、
すでに master は2ヶ月ほどこの状態でいるようです。危ない。

修正内容は単純に

Fork 数からすると Rails 向け APN としてはこちらの方がメジャーなのかも(知らんかった)ですが、ruby で PUSH 通知を組んでいる方は一応ご注意ください。

何が怖いって、PUSH 通知はユーザからフィードバックが無いとどうなっているかわからないところですよね。。
Sandbox で1台や2台のデバイスにテストしたところで気付きにくいし。

外部の gem やプラグインもちゃんと中身を把握して使いましょう、という当然の教訓を再度噛み締めつつ。

2013年7月4日
by kazoo
0 comments

rake xxx と bundle exec rake xxx の違い

いまさらだけど整理。

Rails3 で使用するライブラリは、Gemfile に必要な gems の情報を書いて、

すれば良いが、これだとシステム共通の場所にインストールされてしまう。

ので、他のプロジェクトへの影響やバージョン依存問題を回避するために、Bundler を使ってプロジェクトごとに独立に gem をインストールできる。

と、してやれば、Rails のプロジェクトディレクトリ以下の gems に、必要な gem がインストールされる。

一度実行すれば bundler はこのプロジェクトの gem 保存場所を覚えるので、以降は bundle install でよい。
この情報は、各 Rails ディレクトリの
.bundle/config
に記述される。

は、Rails3 の共通のライブラリ保存場所から読み出せという意味であり、

は、プロジェクトのライブラリ保存場所から読み出せという意味になる。

個別のプロジェクトに保存されている gem のリストを見るには、

とすればよい。

参考:
http://q.hatena.ne.jp/1353552605

2013年4月10日
by kazoo
2 Comments

OS X Lionのrbenv環境でruby-2.0.0-p0への更新メモ

Cookpad がさっそく ruby-2.0.0-p0 へ移行なんてカッコイイニュースも流れる昨今。
新しいことはよいことです。速さは正義です。

ということで特に必要に迫られてはないけど 2.0.0-p0 の導入をやってみた。
普通に $ rbenv install するだけですが、MacbookAir にはあっさり入ったのだけど、放置気味の iMac(Lion) でやったら、いくつかつまずいた。ので過程をメモっておきます。
どなたかのトラブルシュートになれば。

現行は 1.9.3-p194。homebrew で入れた rbenv + ruby-build 環境の前提です。
>>>続きを読む