title: Rails preventing duplicates in polymorphic has_many :through associations
body: <p>Is there an easy or at least elegant way to prevent duplicate entries in polymorphic has_many through associations?</p>
  
  <p>I've got two models, stories and links that can be tagged. I'm making a conscious decision to not use a plugin here. I want to actually understand everything that's going on and not be dependent on someone else's code that I don't fully grasp.</p>
  
  <p>To see what my question is getting at, if I run the following in the console (assuming the story and tag objects exist in the database already)</p>
  
  <pre><code>s = Story.find_by_id(1)
  
  t = Tag.find_by_id(1)
  
  s.tags &lt;&lt; t
  
  s.tags &lt;&lt; t
  </code></pre>
  
  <p>My taggings join table will have two entries added to it, each with the same exact data (tag_id = 1, taggable_id = 1, taggable_type = "Story"). That just doesn't seem very proper to me. So in an attempt to prevent this from happening I added the following to my Tagging model:</p>
  
  <pre><code>before_validation :validate_uniqueness
  
  def validate_uniqueness
      taggings = Tagging.find(:all, :conditions =&gt; { :tag_id =&gt; self.tag_id, :taggable_id =&gt; self.taggable_id, :taggable_type =&gt; self.taggable_type })
  
      if !taggings.empty?
          return false
      end
  
      return true
  end
  </code></pre>
  
  <p>And it works almost as intended, but if I attempt to add a duplicate tag to a story or link I get an ActiveRecord::RecordInvalid: Validation failed exception. It seems that when you add an association to a list it calls the save! (rather than save sans !) method which raises exceptions if something goes wrong rather than just returning false. That isn't quite what I want to happen. I suppose I can surround any attempts to add new tags with a try/catch but that goes against the idea that you shouldn't expect your exceptions and this is something I fully expect to happen.</p>
  
  <p>Is there a better way of doing this that won't raise exceptions when all I want to do is just silently not save the object to the database because a duplicate exists?</p>