すがブロ

sugamasaoのhatenablogだよ

Rails3で困っちゃった事リスト

Rails2.x 系の情報だと動かない!!!

Rackアプリケーションになったことやモジュール化を進めた影響だと思うのだけど、Rails2.x系ではうまく行くと書いてあるやり方が Rails3 になってうまくいかなかったりしたので、実際にハマった事をメモしておくよ。
ちなみに、環境は以下の通り

  • Rails 3.0.1
  • Ruby 1.9.2
  • そもそも Rails自体よくわかってない(!)

以下はあくまでも自分自身のログなので、Rails3……というか Rails の作法としてはこうするんだよ、というベストアンサーがあったらぜひ教えてほしいです。

Session をブラウザが終了しても終わらないようにしたい

ログインした後のいわゆる Session の有効期限を変更したい

今までなら

に書いてあるように

ActionController::Base.session_options[:session_expires] = 1.months.from_now

こんな感じで更新できた。
が、Rails3 では ActionController::Base に session_options なんてネーよと言われる。

対応
request.session_options[:expire_after] = 1.months.from_now

このように、 request オブジェクトに設定させる。
アクセス毎に request.session_options.inspect してもなぜか :expire_after は nil になってしまっていて果たしてこれが全うな設定方法なのかは疑問。……たまたま別の要因でうまく行ってるだけかもしれないけれど。

Production モードで動かしたら画像ファイルが見れなくなった

Production モードで send_file で表示してる画像が0byteで見れない

いきなり見れなくなる(エラーとかでない)のでビビった。 public ディレクトリが見れなくなるのとは別の問題で、どうやら Rails3 での不具合?らしい。
この Rails プロジェクトを作ったときは Rails3 RC だったので、解消されているかもしれない。

このような状態になる。

対応

上記のサイトにある通り、 config/environments/production.rb にある

config.action_dispatch.x_sendfile_header = "X-Sendfile"

をコメントアウトにして事なきをえた。
深追いしていないからわからないけれど

にあるようにX-Sendfileに Apache が対応していないからなのかもしれない*1

routes.rb でネストした URL を作りたい

管理者画面を作るときとか

テーブル構成はネストしていない状態で、 controller だけネストさせたい。
例えば、以下のようなURLでhogeテーブルに対する CRUD 操作をしたいとか。
/admin/hoge

対応

routes.rb には以下のように設定する

scope :module => 'admin' do
  match 'admin/hoge' => 'hoge#show'
end

controller はディレクトリ構成とモジュール構成に注意する
app/controllers/admin/hoges_controller.rb

class Admin::HogesController < ApplicationController
(...)
end

view は model_path メソッドを変更する必要がある。
model_path にすると、 /admin にネストしないので、 admin_model_path のようにする必要がある。

Rails.root/lib が読み込まれない

Rails3 から読み込まれなくなったらしい

過去の事をしらないので良くわかってないが、こんな風にすると良いらしい
config/application.rb

    # RAILS_ROOT/lib/hoge_dir/fuga.rb があるような場合を想定
    config.autoload_paths += %W(#{config.root}/lib/hoge_dir)

log ファイルのパスはドコ

Rails が現在使っている log ファイルのパスを知りたい

決め打ちじゃなくて、logger が使ってるパスを知りたい場合。以下のサイトが参考になった。

対応

log.paths ってことは複数存在することを前提にしているようだけど、用途は良くわかってない。少なくとも、狙いのファイルは先頭にあるので*2、以下で取れる。

Rails.configuration.paths.log.paths.first

log ファイルのローテーションしたい

log ファイルを適宜変更させる

ここだと config/environment.rb に書けとあるけど、 Rails3 だと有効ではないっぽい。

対応

しかたないので config/environments/*.rb にそれぞれ記述することにした。
記述内容自体は上記のサイト同様、以下のように書けば良い*3

  config.logger = Logger.new(Rails.configuration.paths.log.paths.first, 'daily')
追記1

id:pinzolo さんにコメント頂きました。
application.rb に書くと良いらしいです。

> ここだと config/environment.rb に書けとあるけど、 Rails3 だと有効ではないっぽい。
以前の config/environment.rb の内容は config/application.rb に変更されてますので、config/application.rb に書けば全環境で読み込んでくれますよ。

追記2

記述する場所云々の話以前に、そもそも Logger クラスを使う*4のは悪手っぽい。例えば log レベルを Rails がよしなに変えてくれてる部分とか config/initializers/ で指定しているログフォーマットとかがぶっ飛ぶ。
おとなしく logrotated でやれってことですかね。

メールの受信(パース)

メールを Rails アプリ側で取り込む場合

ここの「メールの受信」を ISO2022-JP な Subject のメールを食わせるとエンコーディングの不一致で死ぬ*5
正確には Mail クラスのフィールドの取扱い方がまずいようだ。

しょうがないのでモンキーパッチを当てた


ただ、これだと元々の Mail ライブラリのテストで何件か fail してしまうので、良い直しでは無い。本当に、その場しのぎである。
また、この対応でサブジェクトは対応できるが、添付ファイル名のエンコーディングにはうまく対応できていないので、そちらはそちらで別途対応を考える必要がある。
今回は妥協できる範囲だったので、上記の対応で辞めてしまったのですが、これ、みんな困ってないのかしら???

*1:有効にする、というような設定はしていないので

*2:1ファイルしか無いけど

*3:パスの取得方法上記のURLからは変更している

*4:というか new して上書きしてる

*5:Subject が UTF-8 の場合は、デフォルトエンコーディングがUTF-8だと偶然によってちゃんと動く。本当は複数行の Subject フィールドを連結する際に一つのエンコーディングに統一する必要がある