Posts Tagged ‘Rails’

1 | No Comments | 2月 23rd, 2010

Shop has_many Items という状況のとき、とある shop が持っている items を、下記のように取ることが出来ます。それに対して、条件を設定することも出来ます。

>> @shop.items 
=> [Item id:21 shop_id: 1, Item id: 22, shop_id: 1, ....]
>> @shop.item.find_all_by_category("CPU") 
=> [Item id:23 shop_id: 1, Item id: 26, shop_id: 1, ....]

そこで、同様にとある Shop の Items を全部 delete_all にしようとしたのですが、DELETE されるのではなく、外部キーにNULLがセットされるという挙動になっています。

>> @shop.items.delete_all

とすると

  Item UPDATE (3.0ms)   UPDATE `items` SET shop_id = NULL WHERE (shop_id = 1 AND id IN (22,23,24,25,26))

のようになります。

Rails の API を見ると

# File vendor/rails/activerecord/lib/active_record/base.rb, line 897
897:       def delete_all(conditions = nil)
898:         sql = "DELETE FROM #{quoted_table_name} "
899:         add_conditions!(sql, conditions, scope(:find))
900:         connection.delete(sql, "#{name} Delete all")
901:       end

みたいになっているのですが、Dynamic Scopes はまた別のところで定義されているっぽいです。

>> @shop.items.destroy_all

としてみると、下記のように DELETE になりますが、SQL が発行されまくってるのでだめぽいです。そもそも destroy は、destroy をトリガーにしている各種処理をしてから DELETE が行われるので、そもそも delete とは意味合いが違うというので仕方ないです。

Item Destroy (3.0ms)   DELETE FROM `items` WHERE WHERE id = 21
Item Destroy (3.0ms)   DELETE FROM `items` WHERE WHERE id = 22
Item Destroy (3.0ms)   DELETE FROM `items` WHERE WHERE id = 23

ふつうに Item.delete_all を呼ぶかなぁ

1 | No Comments | 12月 14th, 2009

ようやく最近になって Twitter いいなとか思ってるんですが、毎日自炊してると食べたものを記録したくなって、Twitter から自動的に拾ってくるようなアプリを作ってみた。

食べたものログ(仮) で、@eat_log をフォローすると、フォローしかえされてそこから収集が始まる感じです。それと、よく食べるものを集計して出すっていう機能もついてます。

実装に使ったのは、Rubyの twitter のライブラリと、Yahoo! テキスト解析のキーフレーズ抽出 です。

Yahoo! テキスト解析は、JSONでレスポンス返してくれたりで、すごく簡単に使えます。ruby twitter のドキュメント を見れば、使い方はだいたい分かります。OAuth 認証も簡単でいいです。

未分類 | 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のエラーとか日本語されてる。お手軽ぽ。

download the hurt locker