This was in a content management project where a site may have many pages. Users were able to delete the page, and I wanted to keep the "activity log" complete. So I could refer to the page, but not show it. "Jim deleted the page 'welcome'", for example. Where welcome is the @page.name.
The page name was unique and I didn't want to do anything too complicated to ensure the names were unique - if there was an existing name already, don't allow another. But, if a deleted page had the name 'Welcome', I didn't want to see a validation error.
This is an easy situation to handle...
First, add a mark_deleted method in the Model.
def mark_deleted
self.deleted_at = Time.now
end
def mark_deleted!
mark_deleted
self.save
end
For the name, set the uniqueness validation to have a scope
validates_uniqueness_of :name, :scope => [:parent_id, :deleted_at]
You'll need to add the deleted_at column via a migration
class AddDeletedAtToObject < ActiveRecord::Migration
def self.up
add_column :objects, :deleted_at, :datetime
end
def self.down
add_column :objects, :deleted_at
end
end
When you call the 'destroy' method in the controller, instead of object.destroy!, call object.mark_deleted!
And when referring to parent.objects, call parent.objects.not_deleted, instead.
scope :not_deleted, where('objects.deleted_at is null')