Только один экземпляр модели в Rails

Я работаю над своим первым приложением Rails. Он должен хранить некоторую информацию об одном рекламном объявлении, которое будет отображаться на каждой странице. Администратору просто нужно установить URL, заголовок и изображение. Очевидно, мне нужен только один экземпляр этого рекламного объекта.

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

Как мне лучше всего это сделать? Как должны выглядеть модель и контроллер?

Заранее спасибо, Ави


person Avram    schedule 28.08.2009    source источник


Ответы (4)


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

Затем вы можете проверить в модели, что активна не более одной записи. Проверка активного атрибута должна быть успешной при любом из следующих условий.

  1. Активный атрибут имеет значение false
  2. Есть 0 записей с активным значением true.
  3. Текущая запись уже имеет атрибут, установленный в базу данных как true.

Следующий класс должен удовлетворить ваши потребности

class Ad < ActiveRecord::Base

  named_scope :has_active, :conditions => {:active => true}

  def validate
    errors.add_to_base "You can only have one active advertisement" 
        unless self.active_flag_valid?
  end

  def active_flag_valid?
    self.active == false || 
    Ad.has_active.size == 0 || 
    ( Ad.has_active.size == 1 && !self.active_changed?)
  end
end
person Steve Weet    schedule 28.08.2009
comment
@Avram, нет проблем, однако вы можете посмотреть комментарий @IV относительно автоматической пометки активной в данный момент записи как неактивной, когда другая активна. Мне нравится такой подход больше, чем настаивать на том, чтобы вы деактивировали одно, прежде чем активировать другое. - person Steve Weet; 31.08.2009

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

Внутри вашей модели:

validate :check_record, on: :create #please not that validate in this case is singular

def check_record
 if Ad.all.count === 1
   errors[:base] << "You can only have one active advertisement"
 end
end
person Fatimah    schedule 08.03.2016

Что ж, если вы собираетесь хранить информацию (URL, заголовок, изображение) в базе данных, я думаю, что наследование от AR будет правильным решением. Если они собираются делать это через какой-либо интерфейс, я думаю, что это ваш лучший вариант.

Почему бы не разрешить несколько объявлений, но одновременно можно публиковать только одно из них? Таким образом, у вас также может быть история рекламных объявлений — я не знаю, насколько важна эта часть, но она может оказаться интересной в будущем.

person theIV    schedule 28.08.2009
comment
вау, спасибо за быстрый ответ! Это звучит как хорошая идея. Я предполагаю, что мне придется добавить еще один атрибут, называемый опубликованным, который очищает последнее опубликованное объявление, когда новое создается или устанавливается как опубликованное... - person Avram; 28.08.2009
comment
Да, добавьте логическое значение published, а затем сделайте обратный вызов before_save в своей модели, который найдет ранее опубликованное объявление и отменит его публикацию. Очевидно, вы бы пошли и отменили публикацию старого только в том случае, если бы вы настраивали публикацию текущего. - person theIV; 28.08.2009

Я согласен. Если вы полностью уверены, что он статичен, то его даже не нужно хранить в базе данных. Если он действительно изменится, Rails предоставит вам created_at и updated_at практически бесплатно, поэтому получение последних созданных/обновленных — это один из простых способов отображения того, что является текущим.

person John Lockwood    schedule 28.08.2009
comment
Спасибо Джон, updated_at звучит как более простой способ показать последнее добавленное или обновленное объявление. - person Avram; 28.08.2009
comment
Я думаю, что это тоже хороший подход, хотя я не слишком схожу с ума по поводу чего-то вроде created_at или updated_at на случай, если они готовят будущую рекламу (которая еще не будет опубликована) или модифицируют старая реклама чего-то вроде внутреннего отслеживания, например. через какое-то время у меня появилась куча рекламы под названием «Журнал для активного отдыха», а затем он захотел сделать название «Журнал для активного отдыха, июнь 2009 г.» более явным. Тем не менее, я все еще думаю, что это еще один хороший путь. - person theIV; 28.08.2009
comment
да, я согласен - я думаю, что я буду использовать метод, который вы описали выше, с логическим значением published - person Avram; 29.08.2009
comment
Безусловно, это не единственный способ сделать это — интересны вопросы, возникающие на этапе проектирования. :) - person John Lockwood; 29.08.2009