views:

154

answers:

3

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

+1  A: 

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
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
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
+1  A: 

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
Thanks John, updated_at sounds like a simpler way of showing the most recently added or updated ad.
Avram
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
yes, I agree - I think I'll use the method you described above with the `published` boolean
Avram
To be sure, it's not the only way to do it -- interesting the questions that come up during the design phase. :)
John Lockwood
+1  A: 

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
wow - thanks for your code Steve!
Avram
@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