Ruby on Railsのアプリをサブディレクトリで動かす場合のメモ

たまにRuby on Railsでアプリを作るのだけれどいつも忘れてしまうのでメモ。いろいろな人がすでに書いてるけど自分がよく使う環境に関連したマトメ。Ruby on Rails v4.2.0での動作確認も兼ねて。

## Ajax関連

AjaxでアクセスするURLをJavaScriptでハードコーディングするとサブディレクトリで動かしたときに`404`になって困るのでファイルの拡張子を`js.erb`とか`js.coffee.erb`とかにしてRailsの機能でURLを生成するようにする。

例えばこんな感じ？

```ruby:app/assets/javascripts/application.js.coffee.erb
<%= Rails.application.config.relative_url_root %><%= Rails.application.routes.url_helpers.search_people_path(format:'json') %>
```

なんか一発で取れるメソッドとかありそうな気もするし文字列連結してるのもちょっと嫌な感じもするけど、とりあえずこれで。

で、この`Rails.application.config.relative_url_root`については当該ソースコードを見れば以下のように環境変数`RAILS_RELATIVE_URL_ROOT`の値が代入されていることがわかる。

```ruby:railties-4.2.0/lib/rails/application/configuration.rb
@relative_url_root = ENV["RAILS_RELATIVE_URL_ROOT"]   
```

ちなみに`ActionController::Base.relative_url_root`でも取得できる。当該ソースコードは以下のような感じなので、結局は`Rails.application.config.relative_url_root`経由で`RAILS_RELATIVE_URL_ROOT`由来の値。

```actionpack-4.2.0/lib/action_controller/railtie.rb
options.relative_url_root ||= app.config.relative_url_root
```

`Rails.application.config.relative_url_root`と`ActionController::Base.relative_url_root`の使い分けはよく分からないが、より上流にある前者の方が良い気もするし、コントローラ的には後者の方が良い気もするけど、私は元気です。

## 開発環境

[Rails With Relative URL Root](http://quickhack.net/nom/blog/2012-09-19-rails-with-relative-url-root.html)の「結局おすすめは」を参考にして設定すると変更箇所も少なくうまくいった。

`config.ru`を以下のように書く。ここは`Rails.application.config.relative_url_root`の方がしっくりくる感ある。うむ。

```ruby:config.ru
require ::File.expand_path('../config/environment', __FILE__)
map Rails.application.config.relative_url_root || '/' do
  run Rails.application
end
```

サーバの起動時には環境変数`RAILS_RELATIVE_URL_ROOT`に値を指定する。

```bash
$ RAILS_RELATIVE_URL_ROOT=/piyo rails server
```

あ、最近はspringを使うのかい。インスタンスを再利用してくれて叩き直しが早いらしい。`bundle`とか使ってもう少ししつこく書くとこう。あと`--bind=0.0.0.0`すると他のマシンからでもアクセスできるよ。

```bash
$ RAILS_RELATIVE_URL_ROOT=/piyo bundle exec spring rails server -p 3000 --bind=0.0.0.0
```

ウェブブラウザからは以下のURLでアクセスできる。

```
http://localhost:3000/piyo/
```

## 本番環境

### アセットのプリコンパイル

`production`環境だとデフォルトでは`assets`は動的にコンパイルされないのであらかじめコンパイルしておくのがたぶん普通。こっちの方がはやいもんね。で`rake assets:precompile`がそのプリコンパイルするRakeタスク。初心者はこれで泣きながら１日くらいさまよう罠。この時に環境変数`RAILS_RELATIVE_URL_ROOT`を指定して実行するのを忘れちゃいけない。

うちはDebianなので以下のような感じで実行する。`rake assets:precompile`を実行すると`public/assets`以下へ色々とコンパイルの成果物が配置されるわけだけど`www-data`ってユーザでファイルを生成しとくのがたぶん普通。

```bash
sudo -u www-data -H bundle exec rake assets:precompile RAILS_ENV=production RAILS_RELATIVE_URL_ROOT=/piyo
```

### Passengerの設定

Apache2の設定ファイルは以下な感じにする。`PassengerBaseURI`の値が環境変数`RAILS_RELATIVE_URL_ROOT`にセットされる。この辺は公式サイト参照。あと、`PassengerRuby`で実行させたいRubyの実行ファイルを指定できるので、色んなバージョンのアプリを動かすときに助かる。なお、Passengerは公式マニュアルをよく読んでから使ったほうが良い気がする。急がば回れ。

```:/etc/apache2/sites-enabled/000-default
Alias /piyo /srv/rails/piyo/public
<Location /piyo>
  SetEnv SECRET_KEY_BASE 秘密の文字列
  PassengerEnabled on
  PassengerRuby /usr/local/bin/ruby
  PassengerBaseURI /piyo
  PassengerAppRoot /srv/rails/piyo
  PassengerUser www-data
</Location>
<Directory /srv/rails/piyo/public>
  Options -MultiViews
</Directory>
```

あと、DebianだとPassengerのモジュールの読込設定は`/etc/apache2/httpd.conf`に書くんじゃあない。`/etc/apache2/mods-available`の中を参考に然るべきファイルを設置して`a2enmod`で有効化する。この辺りはDebian流。