(define -ayalog '())

括弧に魅せられて道を外した名前のないプログラマ

Rails で js.erb とかを返却する場合の nginx の設定。

この前、 respond_with(or respond_to) を使えば、 view/some_dir/update.js.erb とか作って直接非同期処理とかで返却出来るよって教えてもらった。要するに画面遷移を起こしたくない場合に結構使えるらしい。

レシピ本にも乗ってるんだけど、見逃していた。(たぶん、読んでたけど、関係ないと思ってて気にしてなかった。勿論、 respond_to は知ってたけど js を返却出来るのは知らなかった。 json or xml or html だけだと思っていた。)

ちなみにそれまでどうしてたかっていうと、 json を返却して ajax の done や fail でレスポンスを受け取って処理を続行していた。けど、直接 js を返却出来て即実行されるのであれば、圧倒的に便利なのは js を返却する方だと思う。

さて、本題。
僕は update.js.coffee を返却したくて、ファイルを置いて開発環境で動くことを確認していた。そして、実際にサーバーにデプロイしたら動かなくなった。ここまで書くと分かると思うんだけど、昨日の夜から今日の朝にかけて騒いでいたのはこれが原因。

で、元々 respond_with を使ったらって教えてくれた人に聞いたら、本番環境で config.serve_static_assets を true にしているとのこと。で、これは Stack Overflow かなんかでも見たけど、やったらアカンと思うのです。なんでかというと、 config/environments/production.rb には Apach か nginx でなんとかしろって書いてあるんですね。*1

# Disable Rails's static asset server (Apache or nginx will already do this).

なので、ここの設定値を変えるのは最終奥義だと思って諦める。そうして、ググってると nginx のフォーラムにあたる。

お、なんか僕と似たような境遇じゃね、この人!って思って読んだら、どうも nginx の設定ファイルが怪しそう。
ということでサーバーの設定ファイルを眺めてたら、以下のような記述があった。

  location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
    expires 1y;
    add_header Cache-Control public;
    log_not_found off;
  }

これが原因では…。と思ってとりあえずコメントアウトしたら、なんと動いた!!元々この設定はどこからやってきたかというと、とりあえず nginx + unicorn でアプリを動かしたい!って思ってわけも分からずコピったもので、今になって思えばそんなよく分からないものコピったのが悪いんですが、思いの外こんなことで躓いている人がいなくて解決するのに手こずったなぁと。

そんな感じで、大変でしたよっと。ちなみに今の設定ファイルこんな感じになってる。

upstream my_app {
  server unix:/tmp/my_app.sock;
}
server {
  listen 80;
  server_name example.com;
  root /home/my_app/public;
  location / {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    if (!-f $request_filename) { proxy_pass http://my_app; }
  }

  # location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
  #   expires 1y;
  #   add_header Cache-Control public;
  #   log_not_found off;
  # }
  location ~ ^/assets/ {
    root /home/my_app/public/;
    expires 1y;
    add_header Cache-Control public;
  }
}

おまけ

view/some_dir/update.js.erb と書いたけど、 update.js.* で suffix は coffee, haml, erb など何でも使えるらしい*2。例えば、 update.js.coffee.haml なんてことも出来るらしいけど、 haml で処理されたあとに coffee として処理されて最終的に js を返却するぽい。まぁ無難なのは混ぜないことだけど、必要とあれば使えるので覚えていて損はなさそう。

*1:訳的には、既に Apache か nginx がやっているはずだよね、って感じだと思うんだけどあってる?

*2:要出典