dchapman
dchapman

Reputation: 365

Has_many through - One Sided Uniqueness in the database

I have a three models:

class Feed < ActiveRecord::Base
  has_many :filters, :dependent => :destroy
  has_many :keywords, :through => :filters, :uniq => true
end

class Filter < ActiveRecord::Base
  belongs_to :feed
  belongs_to :keyword

  validates_uniqueness_of :keyword_id, :scope => :feed_id
end

class Keyword < ActiveRecord::Base
  has_many :filters, :dependent => :destroy
  has_many :feeds, :through => :filters
end

What I want is to have only unique entries in the database for keywords. For example, if two feeds both have a keyword 'hello', there should be two filters (one for each feed) both pointing to the same keyword.

What I am having trouble with is the controller code. Perhaps I am looking for too simple a solution, but I figure there must be an easy way to do this. This is what I have in my create action so far:

def create
  @feed = Feed.find(params[:feed_id])
  @keyword = @feed.keywords.create(params[:keyword])


  redirect_to feed_keywords_path(@feed), notice: 'Keyword added successfully.' 
end

With this controller code, the previous example would result in a duplicate keyword in the database, one for each feed/filter. Is there a straight-forward solution to this or do I need to do a check beforehand to see if there is already a keyword and in that case just create the filter?

Upvotes: 0

Views: 162

Answers (1)

Baldrick
Baldrick

Reputation: 24340

Use a dynamic finder find_or_create_by :

def create
  @feed = Feed.find(params[:feed_id])
  @keyword = Keyword.find_or_create_by_keyword(params[:keyword]) # I assume here that you have a column 'keyword' in your 'keywords' table
  @feed.keywords << @keyword unless @feed.keywords.all.include?(@keyword)

  redirect_to feed_keywords_path(@feed), notice: 'Keyword added successfully.' 
end

Upvotes: 1

Related Questions