2009-06-06 7 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 

EDIT:

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 

...これはかなりです:Freenodeのの#rubyonrails上AnalogHoleからのキューイングは、我々はこれを行うことができますクールで、構文を少し上手くする。

しかし、これは私が望むのと同様に動作しません。特に、それは、より良いfind chaining(すべての条件が得られるまで、このfindを実行しないような)を可能にしません。

さらに重要なことは、: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(のための1つは、実際に存在するため各サイズ)、それを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?などのメソッドを追加して、これをクリーンアップすることができます。

個人的には、Paperclipプラグインをチェックして、これらの問題を完全に回避することをお勧めします。

EDIT:あなたのコメントパー

、「アバター-有するユーザーが私を見るコメント」のような条件を作成するために、私はそれを行うだろうことはよく分かりません。

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

end 

EDIT:

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

あなたはむしろ条件よりも、キャッシングでのみ興味があるので、我々は条件配列をドロップすることができますあなたは関係それほどのように作ることができると思います

私は上記のコードをより実行可能に改訂しました。主な違いは、アセットの「アバター」を簡単に照会できるようにすることです。既存のavatar_assetsを更新して 'avatar- [login]'パターンを含むファイル名にすることができれば、ユーザーログインに基づいて常にアバターを検索するよりもはるかにクリーンな条件セットを静的にすることができます。アソシエーションの拡張もこれを解決するもう一つの方法ですが、私はそれらを連鎖させることや名前付きスコープと組み合わせることはできないと思います。

+0

私は実際にPaperclipを見ました。それは私が必要とするより洗練された機能のいくつかが欠けています。 (資産は私のアプリではあまり使われていませんが、多くの場所で、時には多態的に使用されます;資産タイプごとに1つのpsuedocolumnを持つことは悪いでしょう) – Sai

+0

また、私は次のようなことを可能にする方法はありますか:Post.find(1).comments (:include => {:users => {:avatar_asset =>:thumb}})? – Sai

+0

...また、AFAICTコードが機能しません。必要な:class_nameと:foreign_keyを追加しても、あなたのavatar_assets barfs: 'Unknown column 'users.asset_id'''は、それがどんなユーザーであるかを知らないためです。しかし、これが私をより良いものに導いてくれると思います。関連付けの拡張について再読する必要があります。 – Sai

関連する問題