可以成对组合的类似实体的数据库模式(ActiveRecord)

database schema for like entities that can be combined pairwise (ActiveRecord)

我正在设计一个木管乐器声音的数据库,我想创建一个 table 来连接表演者可以组合成的声音对,例如颤音。这种关系是传递性的:如果声音 A 和声音 B 有 'Sound Relation',那么声音 B 和声音 A 有相同的 'Sound Relation'。

我熟悉join tables,但是没见过他们用来join 'like'对象,只能join 'unlike'对象,比如tags和posts,所以我对那个方向持谨慎态度。

我意识到下面的示例看起来非常可疑,但它给出了我所追求的目标的想法。什么是更好的方法? (使用 ActiveRecord 语法)

型号

class Sound < ActiveRecord::Base
  has_many :linked_sounds, through: :sound_relations, class_name: "Sound", foreign_key: ???
end

class Sound_Relation < ActiveRecord::Base
  has_many :sounds
end

迁移

class CreateSoundRelations < ActiveRecord::Migration
  def change
    create_table :sound_relations do |t|
      t.integer first_sound_id  # This cannot possibly be right.
      t.integer second_sound_id # Surely the transitivity of the 
                                # relationship should be more evident?
    end
  end
end

您可以尝试类似的方法:

class Set  < ActiveRecord::Base
  has_many :sound_sets
  has_many :sounds, :through => :sound_sets
end

class SoundSet < ActiveRecord::Base
  belongs_to :sound
  belongs_to :set
end

class Sound < ActiveRecord::Base
  has_many :sound_sets
  has_many :sets          , :through => :sound_sets
  has_many :set_sound_sets, :through => :sets          , :source => :sound_sets
  has_many :set_sounds    , :through => :set_sound_sets, :source => :sound
end

所以,不再有 "sound_1" 和 "sound_2" ...它们都只是声音。对于每个声音,您还可以使用 set_sounds 方法来检索与其关联的所有声音。

这也允许关系中有两个以上的声音,您可能想在集合模型上添加 "type"。

编辑:如果您查看生成的查询,您会发现其中两次提到 sound_sets,一次使用不同的别名。消除 "self" 连接的关键是在关联中包含一个子句,如下所示:

has_many :set_sounds    ,
         {where("sound_sets.sound_id != set_sound_sets_sound_set_sounds.sound_id")},
         :through => :set_sound_sets,
         :source => :sound    

... 其中 "sound_set_sounds" 是 table 别名。如果你可以 post 评论中的查询,我可以用实际别名更新它。