Измените метод поиска с параметрами на ассоциацию - PullRequest
0 голосов
/ 06 июня 2009

Как мне превратить это в ассоциацию 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

РЕДАКТИРОВАТЬ: Cuing из 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)} будет хорошим первым проходом.

На самом деле это не работает (self == Пользователь), но правильно по духу:

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

(также опубликовано Refactor My Code .)

1 Ответ

0 голосов
/ 07 июня 2009

Так как на самом деле есть несколько 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? и т. Д. Методы для пользователя, чтобы очистить это.

Лично я советую вам проверить плагин 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]», вы можете сделать набор условий статическим, что намного чище, чем необходимость всегда искать аватар на основе имени пользователя. Расширения ассоциации - это еще один способ решения этой проблемы, однако я не думаю, что вы сможете их связать или объединить с именованными областями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...