Upgrading from Rails 2.3.8 to 2.3.14: find_or_create_by on associations changed

Update: I’m not the first one to run into this: lighthouse ticket find_or_create-via-has_many-fails-for-hash-parameters and rails/rails#207.
Between 2.3.8 and 2.3.9 a change was added to ActiveRecord::Associations::AssociationCollection#method_missing that caused find_or_create_by_* to no longer accept hashes as arguments. An app I was upgrading from 2.3.8 ran into this as it passed hashes to a find_or_create_by_* call.

The symptom was that foobar in find_or_create_by_foobar became a serialized hash when saved to the database, instead of the string I was expecting.

The reason it was changed was to ensure that the caches on the collection were updated properly (lighthouse 1108) & (commit fad166c1), which is pretty important, but the fix didn’t take into account dealing w/ two of the cases that find_or_create_by_* accepts when called on an ActiveRecord class:

  • post.comments.find_or_create_by_body :body => 'bar', :type => 'baz'
  • post.comments.find_or_create_by_body 'bar', :type => 'baz'

The new behavior looked like this:

I wrote a patch for it (github.com/rails/rails/pull/4331). Then I found out that 2.3 is only accepting security patches, so I closed it.

If you run into this and you want to use my patch, refer to gist 1586708 which has a monkey patchified version of it. If you want to work around the bug, you can use the optional block to set the attributes you were passing in the hash.

Tags:

Comments are closed.