Rails: использование will_paginate со сложной ассоциацией find - PullRequest
5 голосов
/ 19 мая 2010

Я столкнулся с проблемой с will_paginate при выполнении сложного поиска.

:photo  has_many   :tags,   :through => :tagships
:item   has_many   :photos
:photo  belongs_to :item


@photos = @item.photos.paginate :page => params[:page],
                                :per_page => 200,
                                :conditions => [ 'tags.id IN (?)', tag_ids],
                                :order => 'created_at DESC',
                                :joins => :tags,
                                :group => "photos.id HAVING COUNT(DISTINCT tags.id) = #{tag_count}"

Я хочу получить все фотографии, у которых есть все теги в массиве tag_ids. В MySQL IN обычно выполняет поиск «или», но мне нужны «и». Я нашел, как изменить IN, чтобы имитировать "и" поведение здесь , и это прекрасно работает при использовании model.find (), также работает до тех пор, пока количество извлекаемых записей меньше, чем my: per_page count. Но если он разбит на страницы, генерируемый SQL похож на:

SELECT count(*) AS count_all, photos.id HAVING COUNT(DISTINCT tags.id) = 1 AS photos_id_having_count_distinct_tags_id_1 FROM `photos`(...)

, который не работает. Другие видели эту ошибку и смогли убрать их count () из запроса, но я не думаю, что это возможно в моем случае.

Есть ли лучший способ сделать этот поиск, который может работать с will_paginate? Если это единственный способ сделать это, я думаю, мне стоит поискать другой плагин для разбивки на страницы?

Спасибо!

Ответы [ 2 ]

4 голосов
/ 03 июня 2010

К вашему сведению, вот что я наконец нашел, чтобы это исправить:

@photos = WillPaginate::Collection.create(current_page, per_page) do |pager|
    result = @item.photos.find :all, :conditions => [ 'tags.id IN (?)', tag_ids] ,:order => 'created_at DESC', :joins => :tags, :group => "photos.id HAVING COUNT(DISTINCT tags.id) = #{@tags.count}", :limit => pager.per_page, :offset => pager.offset
    pager.replace(result)

    unless pager.total_entries
      pager.total_entries = @item.photos.find(:all, :conditions => [ 'tags.id IN (?)', tag_ids] ,:order => 'created_at DESC', :joins => :tags, :group => "photos.id HAVING COUNT(DISTINCT tags.id) = #{@tags.count}").count
    end
  end

Вы должны вручную построить разбитый на страницы набор, используя номер страницы в качестве смещения и используя теги для создания запроса на объединение. Вроде неуклюжий.

1 голос
/ 03 июля 2010

Мой первый удар по этому (извините, у меня нет времени, чтобы проверить это прямо сейчас ... обновится, если я сделаю это) будет выглядеть примерно так (добавлено: выберите и измените группу:):

@photos = @item.photos.paginate :page => params[:page],
                                :per_page => 200,
                                :select => "photos.*, COUNT(DISTINCT tags.id) AS tag_count",
                                :conditions => [ 'tags.id IN (?)', tag_ids ],
                                :order => 'created_at DESC',
                                :joins => :tags,
                                :group => "photos.id HAVING tag_count = #{tag_count}"
...