CentOS 5 + REE 1.8.7 + Rails 3.2 + RailsAdmin + Dragonfly 0.8とかの話

新しくプロトタイプを作るのに Rails 3.2 を使ってみた。感想とハマりメモともろもろ。

環境

  • CentOS 5
  • REE 1.8.7
  • Rails 3.2
  • RailsAdmin ( Rails 3.1+ / Dragonfly 0.9+ )
    • bootstrap-sass
    • Devise
    • CanCan
  • Dragonfly 0.8
  • bootstrap-sass-rails
  • kaminari
  • html5_validators

Rails 3.2

インストールとかは別に苦労ないので省略。

RailsAdmin でハマったこと

sferik/rails_admin

  • Devise で AdminUser っていう管理ユーザー用の Model を作ろうとすると動かない
    • routes.rb の記述を RailsAdmin 標準とは逆に devise_for -> engine の mount の順にすると ok
  • RailsAdmin の日付の解釈が生々しくて ja locale をそのままバンバン当てると全部 invalid になる
    • ja.date.formats.admin: '%Y/%m/%d (%a)' みたいにしておいて RailsAdmin から format 指定をこっちに向けると通る
  • :inverse_of なんてついてない
    • これついてないと associate 先の編集とかうまく機能しない

RailsAdmin 動かすまで :inverse_of は知らなかったけど、これいいですね。情報が少ないけど、SQL の発行が減るのでどんどん使いたい。

cf. RailsAdminがリダイレクトループする場合はdeviseとmountを入れ替える — Gist

Devise + CanCan

Devise とか分かんなかったけど、RailsAdmin の generator が親切ではいはいって言ってれば使えるようになる。

Devise は基本的には認証しか考えてないので、権限の分離は CanCan で行う。その際、role 用の field は自分で作るようだ。RailsAdmin インストール時の Devise のために作られる table にはそういう情報を入れておく場所はない。自分で考えて自分で作る。

CanCan はふざけた名前だなと思ったけど、まぁ記述はシンプルだしデフォルトの設定も楽なので、これはよいと思う。CanCan 使わないとしてもユーザー用の table にそれっぽい field があって値は残るわけだから、なんかもっといいものが出てきても乗り換えられそう。

Dragonfly 0.9 でハマったこと

Dragonfly 0.9 は標準では RMagick を使わないんだけど、そうするとなぜか Linux でだけ identify に失敗するという謎現象が起きた。手元の Mac では大丈夫なのでたぶん ImageMagick のバージョンの違いかなぁと思いながら、Dragonfly-RMagick なんてものがあるじゃんと思ったらこれは RMagick 2 系で、RMagick 2.x は CentOS 5 でフツーに使える ImageMagick とは合わない。(6は知らない)

つーことで実績のある Dragonfly 0.8 系にスイッチ。

しようとしたら RailsAdmin が 0.9 以降を要求していたんだけど、RailsAdmin を clone してきて一部直したり Model に直接手を加えたりしてとりあえず動くようにした。(bundler で gem を管理している現代はこんなの簡単にできる。)これでとりあえず安定してる。

Paperclip に Ruby 1.8 + Rails 3.2 で動くバージョンがあればそれを採用する方が楽なような気がしないでもない。時間が取れたらというかどっかに動作実績があればそっちに転ぶかも。(ぐぐったけどすぐ見つからなかったのでとりあえず諦めた。)

therubyracer

execjs が今年の 5月に spidermonkey runtime を deprecated にしたので therubyracer gem をインストール。意外にすんなりできた。心配する必要なかった。

bootstrap-sass-rails

yabawock/bootstrap-sass-rails · GitHub

bootstrap 系の gem がすごく多くて意味が分からないんだけど、RailsAdmin を使っていないなら twitter-bootstrap-rails がいいと思う。generator も親切。でも RailsAdmin とぶつかるので bootstrap-sass-rails にした。

3.1 以降標準の sass-rails にだけ依存してる素直ないい子。

※ デフォルトだと application.css で @import "twitter/bootstrap" しただけだと responsive にならない。@import "twitter/bootstrap/responsive" も要る。

bootstrapとkaminari

きれいにハマった。ポイントは簡単で、

全部 a に入れろ

だった。非 JS 環境を考えると普通 link しない current page などは a なしで書いてしまうが、そうやると bootstrap の pagination の装飾がうまく動かない。

nestedなvalidationのあるModelに素朴にseedを突っ込む

validates :photos, :presence => true unless defined? Rake

みたいなことして回避した。いいのかな。いいよね。

あーでもこれだと rake spec 中も回避しちゃうね。また考えるか。本当のこと言うと end-to-end でテストすればいいのかもしれないけど、RailsAdmin は JavaScript バリバリなのでちゃんと request spec 動かせるか心配。

capistrano/ext/multistageとrsync_with_remote_cache

vigetlabs/capistrano_rsync_with_remote_cache

  • 最近の capistrano は capistrano-ext の機能は同梱
  • rsync_with_remote_cache を使うと remote には scm 要らない
config/deploy.rb

require 'capistrano/ext/multistage'

を追加し、

config/deploy/staging.rb

を用意して

set :rails_env, "staging"

set :deploy_via,   :rsync_with_remote_cache
set :scm,          :git
set :repository,   "."
set :deploy_to,    "/path/to/app"
set :copy_exclude, %w(
  .git
  db/*.sqlite3
  log/*
  *~
)

みたいにする。deploy 先のサーバの参照できる場所に scm はなくてもよい。その代わり rsync がないとダメ。これはこれでよいな。

assetsのprecompileとfallback

まだ production で動かしてないんだけど。

config/deploy.rb

にデフォルトではコメントアウトされてる

load 'deploy/assets'

を足すだけで deploy したら remote で assets を precompile してくれる。ただし staging で動かす場合は

set :rails_env, "staging"

をちゃんと用意しておくこと。

考えたら precompile してくれるなら therubyracer は production サーバに要らねんじゃね?と思わなくもないけど、現段階ではあまり細かく気にしないようにしよう。たぶん local で compile して上げるって方法もあるんだろうけど、とりあえずこのままで。

とか考えてる人がいるみたいだ。確かに precompile が入ると deploy の時間が長くなる。

config/environments/staging.rb

config.assets.compile = true

があれば precompile に失敗してても大丈夫なように見えるんだけど、うまくいってんだかいってないんだかよく分かんない。今のところ precompile で困ってない。

databaseはとりあえずSQLiteをsharedに

config/database.yml

staging:
  adapter: sqlite3
  database: ../../shared/db/staging.sqlite3
  pool: 5
  timeout: 5000

にするといいんだけど rails の process owner と db の owner が合わない場合もあるので、

config/deploy/staging.rb

namespace :db do
  desc 'make shared db directory writable'
  task :writable do
    sudo "chmod -R go+w #{shared_path}/db"
  end
end
before 'deploy:restart', 'db:writable'

こんなことしてこの shared の db を world writable にしちゃう! いいんだ、staging なんだよ!

PassengerのSUB URI

 RackEnv staging
 RackBaseURI /hoge

してる場合

config/environments/staging.rb

config.action_controller.relative_url_root = '/hoge

しておく。これでも別 Engine (RailsAdminなど)からの routing などは一筋縄ではいかない。SUB URI めんどくさい。

幸い production は SUB URI にならない予定だけど。

RailsAdminのShow in App差しかえ

RailsAdminの

lib/rails_admin/config/actions/show_in_app.rb

       register_instance_option :controller do
         Proc.new do
           redirect_to main_app.url_for(@object)
         end
       end

こんなコードがあって、RailsAdmin 上から確認のアイコンなどをクリックするとその resource のフロントエンドに直接リンクを飛ばしてくれる機能がある。

んだけど、RailsAdmin 標準というか行儀のいい resource を routes.rb に書いてないとうまく動かない。

仕方ないのでこれパクって

config/initializer/rails_admin.rb

内で似たような action 書いて url_for の部分をどうにかした。RailsAdmin の config 周りは全体的によくできてると思うんだけど、残念ながら actions 周りはまだだいぶ気が利かない感じなのでこれからどんどん DSL も変わっていきそうな予感。

More