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

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.


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.


@user = User.find_by_email(‘[email protected]’, :conditions => {:state => ‘passive’})
User Load (0.000426) SELECT * FROM users WHERE (
= ‘[email protected]’) AND (users.state = ‘passive’) LIMIT 1
=> nil

@user = User.find_all_by_email(‘[email protected]’, :conditions => {:state => ‘passive’})
User Load (0.000425) SELECT * FROM users WHERE (
= ‘[email protected]’) AND (users.state = ‘passive’)
=> []

EXAMPLE : find_or_(create|initialize)by* IGNORES CONDITIONS

@user = User.find_or_create_by_email(‘[email protected]’, :conditions => {:state => ‘passive’})
User Load (0.000436) SELECT * FROM users WHERE (
= ‘[email protected]’) LIMIT 1

@user = User.find_or_initialize_by_email(‘[email protected]’, :conditions => {:state => ‘passive’})
User Load (0.000409) SELECT * FROM users WHERE (
= ‘[email protected]’) LIMIT 1
=> #<User id: 2, login: nil, email: “[email protected]”, 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>



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