如何将其变成 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 + "_%"]
(也发布在重构我的代码。)