説明のために、SQLite を使用して新しい Rails (3.2.13) プロジェクトを作成します。
rails new TestApp
cd TestApp/
rake db:create
rails g model Blog name:string description:string
rake db:migrate
モデルの内容ですBlog
。
class Blog < ActiveRecord::Base
attr_accessible :description, :name
after_create :print_other_name
private
def print_other_name
# Just for example, running a query here.
blog = Blog.first
end
end
次に、を開きますrails console
。
1.9.3-p125 :001 > blog = Blog.where( name: 'First Blog' ).first_or_create!( description: 'This is the first blog' )
Blog Load (0.2ms) SELECT "blogs".* FROM "blogs" WHERE "blogs"."name" = 'First Blog' LIMIT 1
(0.1ms) begin transaction
SQL (63.9ms) INSERT INTO "blogs" ("created_at", "description", "name", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Thu, 09 May 2013 11:30:31 UTC +00:00], ["description", "This is the first blog"], ["name", "First Blog"], ["updated_at", Thu, 09 May 2013 11:30:31 UTC +00:00]]
======>>>>>>> Blog Load (0.6ms) SELECT "blogs".* FROM "blogs" WHERE "blogs"."name" = 'First Blog' LIMIT 1
(1.5ms) commit transaction
=> #<Blog id: 1, name: "First Blog", description: "This is the first blog", created_at: "2013-05-09 11:30:31", updated_at: "2013-05-09 11:30:31">
上記のコード ブロックで、クエリの後に実行されたクエリを見てくださいINSERT
。
Blog Load (0.6ms) SELECT "blogs".* FROM "blogs" WHERE "blogs"."name" = 'First Blog' LIMIT 1
Blog.first
これは、モデルの の行によって生成されたクエリですafter_create
。
LIMIT 1
条件のない単純なクエリであったはずのものが、クエリにname
条件が追加されました。そして、いろいろテストした結果、追加される条件は、そのBlog.where( name: 'First Blog' ).first_or_create!....
行に記載されている条件であることに気付きました。
つまり、前に使用した条件は、コールバックで実行されるすべてのクエリに自動的に追加されるようです。where
first_or_create
after_create
なぜこれが予想される動作なのか想像できませんが、そうであれば、どこにも文書化されていません。
誰かがこの行動について何か洞察を持っていますか? これは、コールバックですべてのクエリを壊していafter_create
ます。