ruby on rails - When using first_or_create, in the after_create callback, the Model queries get extra conditions added automatically -
for explanation purposes, i'm going create brand new rails (3.2.13) project using sqlite.
rails new testapp cd testapp/ rake db:create rails g model blog name:string description:string rake db:migrate
this content of blog
model.
class blog < activerecord::base attr_accessible :description, :name after_create :print_other_name private def print_other_name # example, running query here. blog = blog.first end end
then open rails console
.
1.9.3-p125 :001 > blog = blog.where( name: 'first blog' ).first_or_create!( description: 'this first blog' ) blog load (0.2ms) select "blogs".* "blogs" "blogs"."name" = 'first blog' limit 1 (0.1ms) begin transaction sql (63.9ms) insert "blogs" ("created_at", "description", "name", "updated_at") values (?, ?, ?, ?) [["created_at", thu, 09 may 2013 11:30:31 utc +00:00], ["description", "this first blog"], ["name", "first blog"], ["updated_at", thu, 09 may 2013 11:30:31 utc +00:00]] ======>>>>>>> blog load (0.6ms) select "blogs".* "blogs" "blogs"."name" = 'first blog' limit 1 (1.5ms) commit transaction => #<blog id: 1, name: "first blog", description: "this first blog", created_at: "2013-05-09 11:30:31", updated_at: "2013-05-09 11:30:31">
in above code block, please @ query has been run after insert
query:
blog load (0.6ms) select "blogs".* "blogs" "blogs"."name" = 'first blog' limit 1
this query has been generated blog.first
line in model's after_create
.
what should have been simple limit 1
query without conditions, has name
condition added on query. , after lot of testing, realised condition being added on condition mentioned in blog.where( name: 'first blog' ).first_or_create!....
line.
in other words, whatever conditions use in where
before first_or_create
seems added automatically queries run in after_create
callback.
i can't imagine why expected behaviour, if is, can't find documented anywhere.
does have insight behaviour? breaking queries in after_create
callbacks.
the first_or_create
wraps whole query in scope defined clause. can solve in 2 ways:
instead of using
first_or_create
usefind_or_create_by
blog.find_or_create_by( name: 'first blog' )
use
unscoped
in callbacks includes query like:def print_other_name # example, running query here. blog = blog.unscoped.first end
Comments
Post a Comment