рельсы 3 + активная запись: есть ли умный способ "кругового" порядка записей - PullRequest
1 голос
/ 02 июля 2011

(действительные числа в 100 раз больше, но их проще объяснить следующим образом)

У нас есть набор из 100 отзывов для 5 ресторанов. В некоторых ресторанах 3 или 4 отзыва, в некоторых - 20-30 отзывов.

В настоящее время у меня есть простой отчет, который упорядочивает их от самых новых до самых старых:

@reviews = Review.joins(:store). 
where('reviews.published= ?',true). 
order("reviews.created_at DESC")

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

most recent for restaurant #A 
most recent for restaurant #B 
...
most recent for restaurant #E

затем повторите для следующего самого последнего для #A, #B, ... # E

и т.д.

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

Нетрудно сделать это медленным способом в коде, но мне интересно, есть ли более быстрый / лучший подход activerecord?

===

Есть ли способ (а) сортировать по ресторанам, (б) создать временный столбец «счетчик», который считает от 1 до N для каждой записи для каждого ресторана, (в) пересортировать по этому столбцу счетчика? Это сделало бы это.

Например, после (a) и (b) набор записей будет

A , <some review>, 1
A , <some review>, 2
...
A , <some review>, 23

B , <some review>, 1
B , <some review>, 2
...
B , <some review>, 11

C , <some review>, 1
C , <some review>, 2
...
C , <some review>, 9

Если бы я мог затем отсортировать этот набор записей на счетчике, он бы использовал циклический перебор A, B, C и т. Д.

Ответы [ 2 ]

1 голос
/ 25 апреля 2018

Я недавно реализовал нечто похожее на это.В моей модели я создал этот метод:

def self.order_jobs
        ordered_jobs = []
        jobs = Job.all.to_a
        jobs.each do |j|
            ordered_jobs.push jobs.delete_at(jobs.find_index {|j| j.company == 'Redhat'}) unless (jobs.find_index {|j| j.company == 'Redhat'}).nil?
            ordered_jobs.push jobs.delete_at(jobs.find_index {|j| j.company == 'Zapier'})    unless (jobs.find_index {|j| j.company == 'Zapier'}).nil?
            ordered_jobs.push jobs.delete_at(jobs.find_index {|j| j.company == 'Mozilla'}) unless (jobs.find_index {|j| j.company == 'Mozilla'}).nil?
            ordered_jobs.push jobs.delete_at(jobs.find_index {|j| j.company == 'Ubuntu'})    unless (jobs.find_index {|j| j.company == 'Ubuntu'}).nil?
            ordered_jobs.push jobs.delete_at(jobs.find_index {|j| j.company == 'Digital Ocean'}) unless (jobs.find_index {|j| j.company == 'Digital Ocean'}).nil?
        end
        ordered_jobs
    end

Затем в контроллере я просто вызываю Job.order_jobs следующим образом:

def index
    @jobs = Job.order_jobs
  end

В методе order_jobs я начинаю с создания двух массивов.Один с существующими заданиями в БД (jobs), а другой (order_jobs), куда я буду перемещать задания в порядке круговой очереди.Магия в ordered_jobs.push jobs.delete_at(jobs.find_index {|j| j.company == 'Redhat'});это говорит, что найди работу в компании Redhat и перемести ее из массива заданий в массив order_jobs.глупость unless и .nil? позволяет вам проходить мимо этого кода, когда в массиве заданий больше нет элементов, соответствующих заданным критериям.

1 голос
/ 02 июля 2011

Вы можете добавить столбец в БД last_displayed, обновлять его при каждом показе ресторана и всегда сортировать .order('last_displayed').

Я также думаю, что вы можете использовать столбец updated_at, touch запись после ее отображения и сортировка по этому столбцу - таким образом вам не нужно обновлять структуру вашей БД

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