可以成对组合的类似实体的数据库模式(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 评论中的查询,我可以用实际别名更新它。
我正在设计一个木管乐器声音的数据库,我想创建一个 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 评论中的查询,我可以用实际别名更新它。