Hatena::Groupcucumber

カノ エ ノ メモ

2008-01-09

after_initializeに関して

| 12:33

# == after_find と after_initialize は例外

#

# after_find と after_initialize は、例えば Base.find(:all) のような、ファインダによってオブジェクトが検索され、

# インスタンス化されるときにそれぞれのオブジェクトに対して呼び出されるので、パフォーマンス上の制約

# (単純なテストケースで 50% 以上) を組み込むことになります。

# 他の全てのコールバックと異なり、after_find と

# after_initialize は明示的に実装が定義 (def after_find) されているときだけ実行されます。

# その場合、全種類のコールバックが呼ばれます。

http://jror4883.rubyforge.org/svn/trunk/activerecord/lib/active_record/callbacks.rb

昨日after_initializeが動かなかったのは、このためらしい。

さっそく、確認。

class Koibumi < ActiveRecord::Base
  attr_accessor :username
  # before_validates :set_anohito_by_username # この行を削除

  # (略)

  protected
  # def set_anohito_by_username
  def before_initialize # 明示的にbefore_initializeを定義
    unless self.anohito
      self.anohito = Anohito.find_or_create_by_username(self.username) if self.username
    end
  end
end

script/consoleで確認する。

変更前

 >> koibumi = Koibumi.new(:username => 'koibumi', :uta_id => 1)
=> #<Koibumi id: nil, anohito_id: nil, uta_id: 1, created_at: nil, updated_at: nil, passed_at: nil>
>> koibumi.anohito
=> nil

当然だけれど、validationされていないので、koibumi.anohitoはnilになる。

変更後

 >> koibumi = Koibumi.new(:username => 'koibumi', :uta_id => 1)
=> #<Koibumi id: nil, anohito_id: 2, uta_id: 1, created_at: nil, updated_at: nil, passed_at: nil>
 >> koibumi.anohito
=> #<Anohito id: 2, username: "koibumi", created_at: "2008-01-09 12:36:43", updated_at: "2008-01-09 12:36:43">

newでusernameを渡しただけで、koibumi.anohitoが入ってる!