2009-06-06 47 views
0

如何將其變爲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 

編輯:從AnalogHole圖定位Freenode上#rubyonrails,我們可以這樣做:

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)}將是一個很好的第一通。

這並不實際工作(個體經營==用戶),而且是正確的精神:

has_many :avatar_assets, :foreign_key => 'creator_id', 
:class_name => 'Asset', :conditions => ["filename LIKE ?", self.login + "_%"] 

(也被張貼在Refactor My Code

回答

0

因爲實際上有多個avatar_assets(一個用於每個尺寸),你必須保持它作爲has_many關聯。

class User < AR::B 
    has_many :avatar_assets, :conditions => ['filename like ?' '%avatar%'], :class_name => 'Asset' 

    named_scope :avatar_size, lambda { |size| 
    { :conditions => [ "thumbnail = ?", size ] } 
    } 
end 

另一種方法是把所有的工作,在一個名爲範圍:

class User < AR::B 
    named_scope :avatar_for, lambda { |user, options| 
    if options[:size] 
    { :conditions => [ "filename like ? AND thumbnail = ?", user.login, options[:size] ] } 
    else 
    { :conditions => [ "filename like ?", user.login ] } 
    end 
    } 
end 

這可以讓你說

Asset.avatar_for(current_user, :size => :medium) 

但不太冷靜,當你發現自己說

current_user.avatar_for(current_user, :size => :medium) 

你可以添加一些:avatar,:avatar?等方法給用戶清理。

我個人建議你檢查回形針插件,並完全避免這些問題。

編輯:

根據您的意見,營造出宛如一個條件「給我具有頭像用戶評論」,我不知道會做到這一點。你可以作出這樣一個關係,以便:

class Comment 
    named_scope :with_avatars, :include => { :user => :avatar_assets }, :conditions => [ 'assets.thumbnail = ?', :thumb ] 

end 

編輯:

,因爲你只在緩存感興趣,而不是條件下,我們可以刪除條件數組:

named_scope :with_avatars, :include => { :user => :avatar_assets } 

我修改了上面的代碼更加可行。關鍵的區別是使資產的「頭像」易於查詢。如果你可以更新現有的avatar_assets,使其包含模式'avatar- [login]'的文件名,你可以使條件設置爲靜態,這比始終必須根據用戶登錄名搜索頭像要乾淨得多。關聯擴展是解決這個問題的另一種方法,但我認爲你不能鏈接它們或將它們與命名範圍結合起來。

+0

我其實看了回形針;它缺少一些我需要的更復雜的功能。 (資產在我的應用程序中很多地方使用,有時是多態的;每種資產類型有一個psuedocolumn會很糟糕。) – Sai 2009-06-07 20:50:02

相關問題