Более простое решение, встроенное в 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
Обратите внимание, добавление опции :uniq => true
к вызову has_many
.
Также вы можете рассмотреть вопрос о has_and_belongs_to_many
между Блогом и Читателем, если у вас нет других атрибутов, которые вы хотели бы иметь в модели соединения (чего у вас нет в настоящее время). Этот метод также имеет опцию :uniq
.
Обратите внимание, что это не мешает вам создавать записи в таблице, но гарантирует, что при запросе к коллекции вы получите только один из каждого объекта.
Обновление
В Rails 4 способ сделать это - через область видимости. Выше изменяется на.
class Blog < ActiveRecord::Base
has_many :blogs_readers, dependent: :destroy
has_many :readers, -> { uniq }, through: :blogs_readers
end
class Reader < ActiveRecord::Base
has_many :blogs_readers, dependent: :destroy
has_many :blogs, -> { uniq }, through: :blogs_readers
end
class BlogsReaders < ActiveRecord::Base
belongs_to :blog
belongs_to :reader
end
Обновление для Rails 5
Использование uniq
в блоке области действия приведет к ошибке NoMethodError: undefined method 'extensions' for []:Array
. Используйте distinct
вместо:
class Blog < ActiveRecord::Base
has_many :blogs_readers, dependent: :destroy
has_many :readers, -> { distinct }, through: :blogs_readers
end
class Reader < ActiveRecord::Base
has_many :blogs_readers, dependent: :destroy
has_many :blogs, -> { distinct }, through: :blogs_readers
end
class BlogsReaders < ActiveRecord::Base
belongs_to :blog
belongs_to :reader
end