Bugs caused by ActiveRecord::Base#first

The latest version of Rails introduces the convenience method “first”
in ActiveRecord, which acts as find(:first). This is breaking my
application wherever the following type of interaction takes place:

blog.posts.first.title = “New title”
blog.save

When blog.save is called, an after_update hook will try to save the
associated posts. But since the line “blog.posts.first” loads a fresh
set of posts from the DB – instead of accessing the in-memory cache
as in previous versions of Rails – the change will not be saved.

The workaround is to say blog.posts[0] instead.

I find this quite insidious, and I’m just curious whether other people
have encountered the same problem, and do you consider this a poor API
change on Rails’ part?

Eric

i personally would never work that far down an object graph, instead i
would do

post = blog.posts.first
post.update_attribute :title, ‘new title’

I would’ve thought #first would’ve been a the #first method from Array.

What do you mean by latest version? Edge or 2.1?

On 21 Jul 2008, at 22:54, Ryan B. wrote:

I would’ve thought #first would’ve been a the #first method from
Array.

What do you mean by latest version? Edge or 2.1?

2.1 adds this. It’s because of the (usually helpful) feature whereby
class methods magically exist on associations

(so if you’ve got
class Post
def self.foo
end
end

then you get blog.posts.foo for free)

I was wondering whether that would cause trouble, although in my mind
I was mostly worrying about unneeded trips to the database.

Fred

In my case, it did cause association to be loaded when I expect it not
to. However, I agree I should have never worked that deep in the
association anyways. I guess it’s just another thing to look out for
in Rails.

On Jul 21, 4:00 pm, Frederick C. [email protected]

On 21 Jul 2008, at 23:41, Frederick C. wrote:

class methods magically exist on associations

I should read the source before I post. foos.first will generate a
find first in some circumstances.
In others (most notably if the association is already loaded) it just
calls first on the already loaded array.
Still there’s definitely potential for errors there.
I would have thought (and my experiments seem to confirm) that you’re
fine with

something.foos.something_that_causes_them_to_be_loaded
something.foos.first

the opposite will cause problems though

Fred