Hey guys,
Have you ever wanted to validate a record was valid for destruction? Does this make sense conceptually? Let me paint a picture of something I just ran into that makes me think I should be able to do this.
I have a many to many polymorphic relationship between our Advertisement model and a bunch of other models in our app. One of these models is the User model. At any point I may want to find the ad for top_dashboard_ad_1 for a given user, but if that user doesnt have an ad specified I want to fall back to our defaults:
@user.ad_for(‘top_dashboard_ad_1’)
class User < AR::B def ad_for(type) advertisements.find_by_location(type) || SiteSettings.instance.ad_for(type) end end
SiteSettings is a singleton model that also has a polymorphic relationship with the Advertisement model. This is all CMS’d. A certain User can have special ads assigned, and the defaults can be changed at any time. Here’s the kicker: If a certain advertisement is associated with the SiteSettings instance (meaning it is a default), I dont want it to allow it to be destroyed.
I currently have this in my Advertisement model:
class Advertisement < AR::B before_destroy :make_sure_not_default
private def make_sure_not_default !(ad_zone_placements.map{|a| a.placement.class}.include? SiteSettings end end
This does prevent the record from being destroyed, but doesnt provide any feedback to the user as to why.
Seems like this should be a validation. I want to be able to use AR::Errors to send a message back to host explaining why it cannot be destroyed, but that behavior kind of flies in the face of the conventional restful controller generated in Rails scaffold (ie: in the destroy action, there is no ‘check for errors and render the edit page’). I feel like I should be able to do:
validates_on_destroy :make_sure_not_default
def make_sure_not_default errors.add_to_base(‘Cannot destroy this AdZone while it is a default’) if ad_zone_placements.map{|a| a.placement.class}.include? SiteSettings end
Right? Has anyone else ever ran into this? Is there something built in I’m missing? Am I have a braindead moment like that time I forgot about “has_many :through” ?
Thanks, Ryan