Friday, July 27, 2007

has_many, finder_sql, and id

Jeez, has it been almost a month since my last post? Time flies when you're a lazy good for nothing.

Anyhow, since It took me some little while to track down this weirdness in rails, I thought I'd give back to the tribe and list the solution here too.

In Rails, you can specify model relationships with cool "macro" methods like 'has_many' and 'belongs_to'. If there is a fairly specific relationship you want to add to a model sometimes you may need to tell rails to just go ahead and use a query instead of the magic. Then you can specify 'finder_sql':

has_many :outstanding_invitations,
:class_name => 'FriendRecord',
:finder_sql => "select * from friend_records
where friend_id = #{id}
and invitation = true"

That's what I started with, but couldn't figure out why I wasn't getting what I wanted, and also getting a deprecation warning: "warning: Object#id will be deprecated; use Object#object_id". After a search I found this article, which has a good tip and the answer. The answer is that #{id} was being "expanded" once it was parsed, so by the time it got to the database it was already the object id, not the active record id. To fix, change the quotes to single quotes or use the %q quote delimiter to stop the id from being expanded.


Aamer said...

Very helpful, thanks.

Juergen said...

This should not be wrapped in double quotes, but single quotes instead.

Tony said...

@Juergen, that's the point of the article.