how to avoid duplicates in a has_many :through relationship? how to avoid duplicates in a has_many :through relationship? ruby ruby

how to avoid duplicates in a has_many :through relationship?


Simpler solution that's built into Rails:

 class Blog < ActiveRecord::Base     has_many :blogs_readers, :dependent => :destroy     has_many :readers, :through => :blogs_readers, :uniq => true    end    class Reader < ActiveRecord::Base     has_many :blogs_readers, :dependent => :destroy     has_many :blogs, :through => :blogs_readers, :uniq => true    end    class BlogsReaders < ActiveRecord::Base      belongs_to :blog      belongs_to :reader    end

Note adding the :uniq => true option to the has_many call.

Also you might want to consider has_and_belongs_to_many between Blog and Reader, unless you have some other attributes you'd like to have on the join model (which you don't, currently). That method also has a :uniq opiton.

Note that this doesn't prevent you from creating the entries in the table, but it does ensure that when you query the collection you get only one of each object.

Update

In Rails 4 the way to do it is via a scope block. The Above changes to.

class Blog < ActiveRecord::Base has_many :blogs_readers, dependent:  :destroy has_many :readers,  -> { uniq }, through: :blogs_readersendclass Reader < ActiveRecord::Base has_many :blogs_readers, dependent: :destroy has_many :blogs, -> { uniq }, through: :blogs_readersendclass BlogsReaders < ActiveRecord::Base  belongs_to :blog  belongs_to :readerend

Update for Rails 5

The use of uniq in the scope block will cause an error NoMethodError: undefined method 'extensions' for []:Array. Use distinct instead :

class Blog < ActiveRecord::Base has_many :blogs_readers, dependent:  :destroy has_many :readers,  -> { distinct }, through: :blogs_readersendclass Reader < ActiveRecord::Base has_many :blogs_readers, dependent: :destroy has_many :blogs, -> { distinct }, through: :blogs_readersendclass BlogsReaders < ActiveRecord::Base  belongs_to :blog  belongs_to :readerend


This should take care of your first question:

class BlogsReaders < ActiveRecord::Base  belongs_to :blog  belongs_to :reader  validates_uniqueness_of :reader_id, :scope => :blog_idend


The Rails 5.1 way

class Blog < ActiveRecord::Base has_many :blogs_readers, dependent:  :destroy has_many :readers,  -> { distinct }, through: :blogs_readersendclass Reader < ActiveRecord::Base has_many :blogs_readers, dependent: :destroy has_many :blogs, -> { distinct }, through: :blogs_readersendclass BlogsReaders < ActiveRecord::Base  belongs_to :blog  belongs_to :readerend