4

I'm working on my first Rails app. It needs to store some information about a single advertisement that will appear on every page. The admin just needs to be able to set the URL, Title, and an image. Obviously, I only need one instance of this ad object.

I created a model that inherits from ActiveRecod::Base, but that seems like the wrong thing to do, since it is configured to save multiple ads in a database table.

What's the best way for me to do this? What should the model and controller look like?

Thanks in advance, Avi

Avram
  • 103
  • 2
  • 5

4 Answers4

6

A better way would be adding a validation that checks if one record entry already exists.

Inside your model:

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
Fatimah
  • 722
  • 7
  • 16
2

Well, if you are going to store the information (URL, Title, image) in the database, I think having it inheriting from AR is the right thing to do. If they are going to do this through any sort of front-end, I think this is your best option.

Why not allow for multiple advertisements, but only one of them can be published at a time? That way, you can also have a history of the advertisements—I don't know how important that part is, but it might prove interesting down the line.

theIV
  • 25,434
  • 5
  • 54
  • 58
  • wow, thanks for the fast response! That sounds like a good idea. I guess I would have to add another attribute called "published" that clears the last published ad when a new one is created or set to published... – Avram Aug 28 '09 at 19:25
  • 1
    Yeah, add a `published` boolean, and then have a `before_save` callback on your model which would find the previously published ad, and un–publish it. Obviously, you'd only go and un–publish the old one if you were setting this current one to be published. – theIV Aug 28 '09 at 19:53
1

I agree. If you're completely sure it's static, then it doesn't even need to be stored in the database. If it does change, Rails will give you created_at and updated_at pretty much for free, so getting the most recently created / updated is one simple way to approach displaying what's current.

John Lockwood
  • 3,787
  • 29
  • 27
  • Thanks John, updated_at sounds like a simpler way of showing the most recently added or updated ad. – Avram Aug 28 '09 at 19:31
  • I think this is a good approach as well, though I'm not too crazy about going by something like `created_at` or `updated_at` in case they might be preparing a future ad (which wouldn't be published yet), or they're modifying an old ad for something like internal tracking, e.g. after a while having a bunch of ads named 'Outdoors Magazine', and then wanting to be a little more explicit in the name 'Outdoors Magazine June 2009'. Though, I still think this is another good way to go. – theIV Aug 28 '09 at 19:32
  • yes, I agree - I think I'll use the method you described above with the `published` boolean – Avram Aug 28 '09 at 20:04
  • To be sure, it's not the only way to do it -- interesting the questions that come up during the design phase. :) – John Lockwood Aug 28 '09 at 20:05
1

I would suggest that you continue using ActiveRecord but that you add a boolean attribute that determines which of the many advertisement records is the active one. I have called this field active within the following example.

You can then validate within the model that a maximum of one record is active. The validation of the active attribute should succeed under any of the following conditions

  1. The active attribute is set to false
  2. There are 0 records with an active value of true.
  3. The current record already has the attribute set to true in the database.

The following class should meet your needs

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
Steve Weet
  • 28,126
  • 11
  • 70
  • 86
  • @Avram, no problems however you might want to look at @IVs comment regarding automatically marking the currently active record as inactive wben another one is set to active. I like that approach better than insisting that you de-activate one before activating another – Steve Weet Aug 31 '09 at 05:14