これを has_one 関連付けにするにはどうすればよいですか?
(おそらく has_one + サイズの名前付きスコープ。)
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
編集: Freenode #rubyonrails の AnalogHole からヒントを得て、これを行うことができます。
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
...これはかなりクールで、少なくとも構文が少し良くなります。
ただし、これはまだ私が望むほどうまく動作しません。特に、それ以上のナイス検索連鎖は許可されません (すべての条件を取得するまでこの検索を実行しないなど)。
さらに重要なことは、:include での使用が許可されていないことです。理想的には、次のようなことをしたい:
PostsController
def show
post = Post.get_cache(params[:id]) {
Post.find(params[:id],
:include => {:comments => {:users => {:avatar_asset => :thumb}} }
...
end
...投稿と一緒にアセットをキャッシュできるようにします。または、実際にはそれらをまったくキャッシュします-たとえばget_cache(user_id){User.find(user_id, :include => :avatar_assets)}
、最初のパスとしては良いでしょう。
これは実際には機能しませんが (self == User)、精神的には正しいです:
has_many :avatar_assets, :foreign_key => 'creator_id',
:class_name => 'Asset', :conditions => ["filename LIKE ?", self.login + "_%"]
( Refactor My Codeにも投稿されています。)