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 调用中。
此外,您可能需要考虑在 Blog 和 Reader 之间使用 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