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

編集: 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にも投稿されています。)

4

1 に答える 1

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 )

、などのメソッドを User に追加して:avatar、これをクリーンアップできます。:avatar?

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

編集:

あなたのコメントによると、「アバターを持つユーザーによるコメントを表示する」のような条件を作成するために、それができるかどうかはわかりません。次のような関係を作成できます。

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]' を含むファイル名を持つようにすると、条件セットを静的にすることができます。これは、常にユーザー ログインに基づいてアバターを検索するよりもはるかにクリーンです。関連拡張はこれを解決する別の方法ですが、それらを連鎖させたり、名前付きスコープと組み合わせたりすることはできないと思います。

于 2009-06-06T23:31:50.320 に答える