我正在设计一个木管乐器声音的数据库,并希望创建一个表格,连接表演者可以组合成的声音,例如,颤音。这种关系是传递性的:如果声音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
答案 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”是表别名。如果您可以在评论中发布查询,我可以使用实际别名更新此信息。