Ruby on rails 如何在多态联接表上强制唯一性?

Ruby on rails 如何在多态联接表上强制唯一性?,ruby-on-rails,unique,polymorphic-associations,jointable,Ruby On Rails,Unique,Polymorphic Associations,Jointable,假设我有一个流派模型,可以与书籍或电影的实例相关联。大概 class Genre < ActiveRecord::Base belongs_to :genreable, polymorphic: true end class Book < ActiveRecord::Base has_many :genres, as: :genreable end class Movie < ActiveRecord::Base has_many :genres, as: :g

假设我有一个流派模型,可以与书籍或电影的实例相关联。大概

class Genre < ActiveRecord::Base
  belongs_to :genreable, polymorphic: true
end

class Book < ActiveRecord::Base
  has_many :genres, as: :genreable
end

class Movie < ActiveRecord::Base
  has_many :genres, as: :genreable
end
…还有一个附带说明:我必须指定索引的名称,因为ActiveRecord自动生成的索引名称超过了64个字符的限制


将所有这些都用于测试运行,并且工作正常。

使用唯一性验证()的:scope属性。例如,在GenResistence模型中,尝试:

class GenreInstance < ActiveRecord::Base

    ...

    validates :genre_id, :uniqueness => {
        :scope => [:genreable_id, :genreable_type]
    }
emd

…但快速测试表明,即使具有多态关联,它也只检查_id字段,因此需要同时指定_id和_type字段。

Spot on on。这非常有用!非常感谢。
class CreateGenreInstances < ActiveRecord::Migration
  def change
    create_table :genre_instances do |t|
      t.references :genre
      t.references :genreable, polymorphic: true

      t.timestamps
    end

    add_index :genre_instances, [:genre_id, :genreable_id, :genreable_type],
      unique: true, name: 'genre_and_genreable'
  end
end
class GenreInstance < ActiveRecord::Base

    ...

    validates :genre_id, :uniqueness => {
        :scope => [:genreable_id, :genreable_type]
    }
emd
class Article < ActiveRecord::Base
    has_many :topic_mappings, :as => :entity, :dependent => :destroy
    has_many :topics, :through => :topic_mappings
end

class Topic < ActiveRecord::Base
    has_many :topic_mappings, :dependent => :destroy
end

class TopicMapping < ActiveRecord::Base
    belongs_to :entity, :polymorphic => true
    belongs_to :topic

    validates :topic_id, :presence => true
    validates :entity_id, :presence => true
    validates :entity_type, :presence => true

    validates :topic_id, :uniqueness => {
        :scope => [:entity_id, :entity_type]
    }
end
:scope => [:model_name]