Change a finder method w/ parameters to an association
Posted
by Sai Emrys
on Stack Overflow
See other posts from Stack Overflow
or by Sai Emrys
Published on 2009-06-06T00:41:41Z
Indexed on
2010/05/09
12:08 UTC
Read the original article
Hit count: 230
How do I turn this into a has_one association?
(Possibly has_one + a named scope for size.)
class User < ActiveRecord::Base
has_many :assets, :foreign_key => 'creator_id'
def avatar_asset size = :thumb
# The LIKE is because it might be a .jpg, .png, or .gif.
# More efficient methods that can handle that are OK. ;)
self.assets.find :first, :conditions =>
["thumbnail = '#{size}' and filename LIKE ?", self.login + "_#{size}.%"]
end
end
EDIT: Cuing from AnalogHole on Freenode #rubyonrails, we can do this:
has_many :assets, :foreign_key => 'creator_id' do
def avatar size = :thumb
find :first, :conditions => ["thumbnail = ? and filename LIKE ?",
size.to_s, proxy_owner.login + "_#{size}.%"]
end
end
... which is fairly cool, and makes syntax a bit better at least.
However, this still doesn't behave as well as I would like. Particularly, it doesn't allow for further nice find chaining (such that it doesn't execute this find until it's gotten all its conditions).
More importantly, it doesn't allow for use in an :include. Ideally I want to do something like this:
PostsController
def show
post = Post.get_cache(params[:id]) {
Post.find(params[:id],
:include => {:comments => {:users => {:avatar_asset => :thumb}} }
...
end
... so that I can cache the assets together with the post. Or cache them at all, really - e.g. get_cache(user_id){User.find(user_id, :include => :avatar_assets)}
would be a good first pass.
This doesn't actually work (self == User), but is correct in spirit:
has_many :avatar_assets, :foreign_key => 'creator_id',
:class_name => 'Asset', :conditions => ["filename LIKE ?", self.login + "_%"]
(Also posted on Refactor My Code.)
© Stack Overflow or respective owner