glenn-jT5ReJafvruGXP9dGu5uFFaTQe2KTcn/@public.gmane.org
2008-Feb-07 01:12 UTC
ActiveRecord ''find_or_initialize_by'' dynamic finder bug? Ignoring conditions.
Hello all, I just ran into something that I think is a bug, and I would like to confirm with the core team whether this is expected/desired behavior or if this is a bug that I should file and develop failing tests for (I doubt I have the active record method_missing fu to actually patch it). Test Scenario: I would like to find or initialize a new user and base the find on the users email address, however the user found has to also match one of two possible ''state'' values (passive || pending_singup). While trying to implement this I discovered that the find_or_(initialize| create)_by_* dynamic finders totally and silently ignore any conditions passed. Bug? Should''nt these dynamic finders behave the same as find_by_* or find_all_by_* dynamic finders and use the :conditions passed to them? The documentation seems to indicate that they should. http://api.rubyonrails.org/classes/ActiveRecord/Base.html Dynamic attribute-based finders "It''s even possible to use all the additional parameters to find. For example, the full interface for Payment.find_all_by_amount is actually Payment.find_all_by_amount(amount, options). And the full interface to Person.find_by_user_name is actually Person.find_by_user_name(user_name, options). So you could call Payment.find_all_by_amount(50, :order => "created_on"). The same dynamic finder style can be used to create the object if it doesn''t already exist. This dynamic finder is called with find_or_create_by_ and will return the object if it already exists and otherwise creates it, then returns it." Here are a couple of examples. I know these are contrived since I could use ''find_or_initialize_by_name_and_state()'' however what I am really trying to show is that the :conditions options are ignored. Check out the actual SQL run by each of these finds in a console to see what I mean. ## EXAMPLE : USES CONDITIONS ##>> @user = User.find_by_email(''foo-+RB1Aph5k6s@public.gmane.org'', :conditions => {:state => ''passive''})User Load (0.000426) SELECT * FROM `users` WHERE (`users`.`email` = ''foo-+RB1Aph5k6s@public.gmane.org'') AND (`users`.`state` = ''passive'') LIMIT 1 => nil>> >> @user = User.find_all_by_email(''foo-+RB1Aph5k6s@public.gmane.org'', :conditions => {:state => ''passive''})User Load (0.000425) SELECT * FROM `users` WHERE (`users`.`email` = ''foo-+RB1Aph5k6s@public.gmane.org'') AND (`users`.`state` = ''passive'') => [] ## EXAMPLE : find_or_(create|initialize)_by_* IGNORES CONDITIONS ##>> @user = User.find_or_create_by_email(''foo-+RB1Aph5k6s@public.gmane.org'', :conditions => {:state => ''passive''})User Load (0.000436) SELECT * FROM `users` WHERE (`users`.`email` = ''foo-+RB1Aph5k6s@public.gmane.org'') LIMIT 1>> @user = User.find_or_initialize_by_email(''foo-+RB1Aph5k6s@public.gmane.org'', :conditions => {:state => ''passive''})User Load (0.000409) SELECT * FROM `users` WHERE (`users`.`email` = ''foo-+RB1Aph5k6s@public.gmane.org'') LIMIT 1 => #<User id: 2, login: nil, email: "foo-+RB1Aph5k6s@public.gmane.org", crypted_password: nil, salt: nil, created_at: "2008-02-07 00:48:48", updated_at: "2008-02-07 00:48:48", remember_token: nil, remember_token_expires_at: nil, activation_code: nil, activated_at: nil, state: "passive", deleted_at: nil, password_reset_at: nil, forgot_password_code: nil, name: nil, beta_code: nil, beta_approved_at: nil> Thanks, Glenn --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Glenn Rempe
2008-Feb-07 01:16 UTC
Re: ActiveRecord ''find_or_initialize_by'' dynamic finder bug? Ignoring conditions.
Here is a pastie of the samples I embedded here which will be easier to read perhaps. http://pastie.caboo.se/148479 Glenn> Hello all, > > I just ran into something that I think is a bug, and I would like to > confirm with the core team whether this is expected/desired behavior > or if this is a bug that I should file and develop failing tests for > (I doubt I have the active record method_missing fu to actually patch > it). > > Test Scenario: > I would like to find or initialize a new user and base the find on the > users email address, however the user found has to also match one of > two possible ''state'' values (passive || pending_singup). While trying > to implement this I discovered that the find_or_(initialize| > create)_by_* dynamic finders totally and silently ignore any > conditions passed. > > Bug? > > Should''nt these dynamic finders behave the same as find_by_* or > find_all_by_* dynamic finders and use the :conditions passed to them? > The documentation seems to indicate that they should. > > http://api.rubyonrails.org/classes/ActiveRecord/Base.html > > Dynamic attribute-based finders > > "It''s even possible to use all the additional parameters to find. For > example, the full interface for Payment.find_all_by_amount is actually > Payment.find_all_by_amount(amount, options). And the full interface to > Person.find_by_user_name is actually > Person.find_by_user_name(user_name, options). So you could call > Payment.find_all_by_amount(50, :order => "created_on"). > The same dynamic finder style can be used to create the object if it > doesn''t already exist. This dynamic finder is called with > find_or_create_by_ and will return the object if it already exists and > otherwise creates it, then returns it." > > > Here are a couple of examples. I know these are contrived since I > could use ''find_or_initialize_by_name_and_state()'' however what I am > really trying to show is that the :conditions options are ignored. > Check out the actual SQL run by each of these finds in a console to > see what I mean. > > ## EXAMPLE : USES CONDITIONS ## > > >> @user = User.find_by_email(''foo-+RB1Aph5k6s@public.gmane.org'', :conditions => {:state => ''passive''}) > User Load (0.000426) SELECT * FROM `users` WHERE (`users`.`email` > = ''foo-+RB1Aph5k6s@public.gmane.org'') AND (`users`.`state` = ''passive'') LIMIT 1 > => nil > > >> >> @user = User.find_all_by_email(''foo-+RB1Aph5k6s@public.gmane.org'', :conditions => {:state => ''passive''}) > User Load (0.000425) SELECT * FROM `users` WHERE (`users`.`email` > = ''foo-+RB1Aph5k6s@public.gmane.org'') AND (`users`.`state` = ''passive'') > => [] > > > ## EXAMPLE : find_or_(create|initialize)_by_* IGNORES CONDITIONS ## > > >> @user = User.find_or_create_by_email(''foo-+RB1Aph5k6s@public.gmane.org'', :conditions => {:state => ''passive''}) > User Load (0.000436) SELECT * FROM `users` WHERE (`users`.`email` > = ''foo-+RB1Aph5k6s@public.gmane.org'') LIMIT 1 > > >> @user = User.find_or_initialize_by_email(''foo-+RB1Aph5k6s@public.gmane.org'', :conditions => {:state => ''passive''}) > User Load (0.000409) SELECT * FROM `users` WHERE (`users`.`email` > = ''foo-+RB1Aph5k6s@public.gmane.org'') LIMIT 1 > => #<User id: 2, login: nil, email: "foo-+RB1Aph5k6s@public.gmane.org", crypted_password: > nil, salt: nil, created_at: "2008-02-07 00:48:48", updated_at: > "2008-02-07 00:48:48", remember_token: nil, remember_token_expires_at: > nil, activation_code: nil, activated_at: nil, state: "passive", > deleted_at: nil, password_reset_at: nil, forgot_password_code: nil, > name: nil, beta_code: nil, beta_approved_at: nil> > > > Thanks, > > Glenn--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---