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.

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@bar.com', :conditions => {:state => 'passive'})

  User Load (0.000426) SELECT * FROM `users` WHERE (`users`.`email` = 'foo@bar.com') AND (`users`.`state` = 'passive') LIMIT 1 => nil

>> @user = User.find_all_by_email('foo@bar.com', :conditions => {:state => 'passive'})

  User Load (0.000425) SELECT * FROM `users` WHERE (`users`.`email` = 'foo@bar.com') AND (`users`.`state` = 'passive') =>

## EXAMPLE : find_or_(create|initialize)_by_* IGNORES CONDITIONS ##

@user = User.find_or_create_by_email('foo@bar.com', :conditions => {:state => 'passive'})

  User Load (0.000436) SELECT * FROM `users` WHERE (`users`.`email` = 'foo@bar.com') LIMIT 1

@user = User.find_or_initialize_by_email('foo@bar.com', :conditions => {:state => 'passive'})

  User Load (0.000409) SELECT * FROM `users` WHERE (`users`.`email` = 'foo@bar.com') LIMIT 1 => #<User id: 2, login: nil, email: "foo@bar.com", 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

Here is a pastie of the samples I embedded here which will be easier to read perhaps.

http://pastie.caboo.se/148479

Glenn