Как мне заказать общий атрибут двух моделей в БД? - PullRequest
1 голос
/ 05 апреля 2010

Если у меня две таблицы Книги, диски с соответствующими моделями.

Я хочу отобразить пользователю список книг и компакт-дисков. Я также хочу иметь возможность сортировать этот список по общим атрибутам (дата выпуска, жанр, цена и т. Д.). У меня также есть базовая фильтрация по общим атрибутам.

Список будет большим, поэтому я буду использовать нумерацию страниц в управлении нагрузкой.

items = []
items << CD.all(:limit => 20, :page => params[:page], :order => "genre ASC")
items << Book.all(:limit => 20, :page => params[:page], :order => "genre ASC")
re_sort(items,"genre ASC")

Сейчас я делаю два запроса, объединяю их и затем сортирую. Это очень неэффективно. Также это ломается, когда я использую пейджинг и фильтрацию. Если я на странице 2, как я узнаю, на какой странице каждой отдельной таблицы я на самом деле? Невозможно определить эту информацию, не получив все элементы из каждой таблицы.

Я имею в виду, что если я создаю новый Класс с именем items, который имеет отношение один к одному с Книгой или CD, и делаю что-то вроде

Item.all(:limit => 20, :page => params[:page], :include => [:books, :cds], :order => "genre ASC")

Однако это возвращает неоднозначную ошибку. Так может быть уточнено только как

Item.all(:limit => 20, :page => params[:page], :include => [:books, :cds], :order => "books.genre ASC")

И не чередует книги и компакт-диски так, как я хочу.

Любые предложения.

Ответы [ 3 ]

1 голос
/ 06 апреля 2010

Идея модели Item будет работать, но вам придется извлечь все общие атрибуты и сохранить их в Item. Затем обновите все формы, чтобы сохранить эти конкретные значения в новой таблице. Таким образом, позднее будет проще добавить другой тип носителя.

Обновление после комментария:

А как насчет союза? Сделай find_by_sql и сделай вручную SQL. Это не будет просто, но ваша схема БД не проста. Так что сделайте что-то вроде этого:

class Item < ActiveModel::Base
  attr_reader :title, :genre, :media_type, ...

  def self.search(options = {})
    # parse options for search criteria, sorting, page, etc.
    # will leave that for you :)
    sql = <<-SQL
    (SELECT id, title, genre, 'cd' AS media_type
     FROM cds
     WHERE ???
     ORDER BY ???
     LIMIT ???
    ) UNION
    (SELECT id, title, genre, 'book' AS media_type
     FROM books
     WHERE ???
     ORDER BY ???
     LIMIT ???
    )
    SQL
    items = find_by_sql(sql) 
  end
end

непроверенных

Или что-то на этот счет. В основном строите строки элементов на лету (вам понадобится пустая таблица элементов). Столбец media_type предназначен для того, чтобы вы знали, как создавать ссылки при отображении результатов.

Или ...

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

0 голосов
/ 06 апреля 2010

Вы говорите, что не можете изменить способ хранения книг и компакт-дисков в базе данных, но не могли бы вы добавить представление items? У вас вообще есть контроль над базой данных?

CREATE VIEW items
  (id, type, title, genre, created_at, updated_at)
  AS
  SELECT b.id, 'Book', b.title, b.genre, b.created_at, b.updated_at
    FROM books b
  UNION
  SELECT c.id, 'CD', c.title, c.genre, c.created_at, c.updated_at
    FROM cds c;
0 голосов
/ 06 апреля 2010

Вы можете разбивать на страницы в массиве результатов, поэтому не включайте нумерацию страниц в запросы отдельных моделей и добавьте их в массив результатов:

re_sort (items, "Жанр ASC"). Paginate (: page => params [: page],: per_page => items_per_page)

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