Posts Tagged ‘Rails’

, | No Comments | 5月 20th, 2009

RailsのActiveRecordで、save! とかすると保存に失敗したとき例外を投げてくれる。例えば、User.create!(params[:user]) とかして、失敗すると、ActiveRecord::RecordInvalid を投げてくれるのだけど、エラーをどうやって取るのか調べたのでメモ。

よくある例で、ユーザが作れたら index へ遷移して、作れなかったら new で再入力させるという場合。

createを使う場合

def create
  if @user = User.create(params[:user])
    flash[:notice] = 'ユーザ作成しました'
    redirect_to :action => 'index'
  else
    # ここでは、@user.errors でエラーが取れる
    render :action => 'new'
  end
end

create!を使う場合

def create
  @user = User.create!(params[:user])
  flash[:notice] = 'ユーザ作成しました'
  redirect_to :action => 'index'
rescue ActiveRecord::RecordInvalid => e
  # @user は nil になっているので、 @user.errors でエラーが取れない。
  render :action => 'new'
end

としたとき、create! で例外が飛んでいるので、当然 @user は nil となってます。なので、rescue 句の中で @user.errors ではエラーが取れません。

調べたところ、e.record で、ActiveRecord の例外を発生させたインスタンスが取れるようです。

def create
  @user = User.create!(params[:user])
  flash[:notice] = 'ユーザ作成しました'
  redirect_to :action => 'index'
rescue ActiveRecord::RecordInvalid => e
  # e.record に Userクラスのインスタンスが入ってる。
  @user = e.record
  render :action => 'new'
end

たとえば、View内で

< %= error_messages_for :user %>

とかしたい場合は、@user = e.record として置けばエラーが楽に表示出来て良い。

| No Comments | 4月 22nd, 2009

プログラム中にコメントで

# TODO 退会のフローについてメール確認待ち 090420

とか書いたりするのだけど、Rails で使ってると rake で一覧を抽出出来る。

% rake notes
app/models/user.rb:
  * [267] [TODO] 退会のフローについてメール確認待ち 090420

よく見てみたら、TODO以外も拾ってくれるようだ。

% rake --tasks
rake notes                           # Enumerate all annotations
rake notes:fixme                     # Enumerate all FIXME annotations
rake notes:optimize                  # Enumerate all OPTIMIZE annotations
rake notes:todo                      # Enumerate all TODO annotations

FIXME, OPTIMIZE, TODO とある。

どんな時に使うのか調べてみたら、

FIXME
修正の必要あり
OPTIMIZE
最適化の必要あり
TODO
TODOのメモ

みたいな感じに使えばいいらしい。

なるほど。

| No Comments | 2月 10th, 2009

Rails2.2.2 で簡単に多言語化(ていっても日本語しかお世話にならなそうだけど)出来てすごい!

% sudo gem so -a http://gems.github.com
% sudo gem i amatsuda-i18n_generators
% ./script/generate i18n ja
% vi config/locales/active_record_ja.yml

すると、なかにごにょごにょ

ja:
  activerecord:
    models:
      user: 'ユーザ'
    attributes:
      user:
        name: '名前'
        email: 'メールアドレス'
....

みたいな感じで書くと、ARのエラーとか日本語されてる。お手軽ぽ。

, | 2 Comments | 2月 10th, 2009

Rails&Lighttpdの環境で動画とか大容量ファイルを高速にダウンロードさせるとき、Rails の send_file を使わずに Lighttpd の X-sendfile という仕組みを使うと良いようです。

lighttpd-1.4.15 で試しました。

通常のsend_file

send_file '/tmp/movie.wmv'

Lighttpdを使ったx-sendfile

# X_SENDFILE する
path = '/tmp/movie.wmv'
response.headers['Content-Type'] = "application/force-download"
response.headers['Content-Disposition'] = "attachment; filename=\"123.mmv\""  # 好きな名前でダウンロードさせる
response.headers["X-LIGHTTPD-SEND-FILE"] = path
response.headers['Content-length'] = File.size(path)
render :nothing => true

これだけではダメで、lighttpdの設定も変更する必要がある。

lighttpdにパスが通ってる環境では lighttpd が優先的に起動されるが、初回起動時に config/lighttpd.conf が生成されるはずで、以下のようなくだりがあるはず。

fastcgi.server      = ( ".fcgi" => ( "localhost" => (
  "min-procs"       => 1,
  "max-procs"       => 1,
  "socket"          => CWD + "/tmp/sockets/fcgi.socket",
  "bin-path"        => CWD + "/public/dispatch.fcgi",
  "bin-environment" => ( "RAILS_ENV" => "development" )
) ) )

ここに、 "allow-x-send-file" => "enable" を追加すると先ほどの X-LIGHTTPD-SEND-FILE が使えるようになります。追加しないと、エラーは起きないけど、1byteの空ファイルしかダウンロードされません。

設定すると、以下のようになります。

fastcgi.server      = ( ".fcgi" => ( "localhost" => (
  "allow-x-send-file" => "enable",
  "min-procs"       => 1,
  "max-procs"       => 1,
  "socket"          => CWD + "/tmp/sockets/fcgi.socket",
  "bin-path"        => CWD + "/public/dispatch.fcgi",
  "bin-environment" => ( "RAILS_ENV" => "development" )
) ) )

x-send-file の注意点ではないですが、IEでは ヘッダに Cache-Control: no-cache がついていた場合、SSLでファイルのダウンロードが出来ないという仕様があります。こういうときは、SSLを経由しないようにするか、no-cache をやめる必要があります。どういう仕様なんだろう…。

どういう条件かわからないが、ファイルが変更されても304 Not Modified が返されてしまうことがあることが発覚。強制的に、200を返してあげれば最新のファイルがダウンロードされます。逆に変更されていない場合は304を返したいので、そういう割り当てをすれば良いのだが。

render :status => 200

とかで、強制的に200を返せるようだ。

| No Comments | 1月 29th, 2009

準備

% sudo gem install diff-lcs redgreen ruby-snarl ZenTest launchy rspec webrat autotest_screen --no-ri --no-rdoc

インストール

%  script/plugin install git://github.com/dchelimsky/rspec.git
% script/plugin install git://github.com/dchelimsky/rspec-rails.git
% script/generate rspec

Railsのバージョンを上げたら、上記のコマンドを実行しないとエラーが出るメソッドがあるので注意。

Rails2.2.2でエラーで動かなかった

vendor/plugins/rspec_on_rails/lib/spec/rails/example/rails_example_group.rb:4:
undefined method `cache_template_extensions=' for
ActionView::Base:Class (NoMethodError)

というエラーが出てテストが実行できなかった。
該当箇所をコメントアウトしても今のところ問題は起きていないので、このまま続けてみようと思う。

#ActionView::Base.cache_template_extensions = false

Growlと連携

まず、Growlの設定で「ネットワーク」の「受信される通知を開く」にチェックを入れる。

あと、growlnotify をインストールしていなかったらインストールする。Growl-1.1.4.dmg をマウントしたら、

% cd /Volumes/Growl-1.1.4/Extras/growlnotify
% sudo ./install.sh

という感じでインストールできます。

あとは、autotest の設定ファイルを ~/.autotest に記述する。growlとautotestを連携させる – Hello, world! – s21g の通りに設定させてもらう。必要あるか分からないけど、一応 Growl の再起動をして試したところ無事動作しました。

動かなかったら、export RSPEC=true をする必要がある。

download the hurt locker