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

时间:2015-08-16 19:31:23

标签: activerecord sinatra-activerecord

我正在设计一个木管乐器声音的数据库,并希望创建一个表格,连接表演者可以组合成的声音,例如,颤音。这种关系是传递性的:如果声音A具有“声音关系”。声音B,然后声音B具有相同的声音关系'声音A。

我熟悉联接表,但我从来没有见过他们习惯加入'喜欢'对象,只是加入'不像'对象,例如标签和帖子,所以我对这个方向持谨慎态度。

我意识到下面的例子看起来非常可疑,但它让我知道我之后会发生什么。这样做的更好方法是什么? (使用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

1 个答案:

答案 0 :(得分:1)

您可以尝试以下方式:

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方法检索与其相关的所有声音。

这也允许关系中有两个以上的声音,你可能想在集合模型上加上“类型”。

编辑:如果查看生成的查询,您会发现两次提到sound_sets,一次使用不同的别名。消除“自我”连接的关键是在协会中包含一个条款:

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”是表别名。如果您可以在评论中发布查询,我可以使用实际别名更新此信息。