我正在尝试查询HABTM自联接,似乎无法正确获取activerecord查询。
目标是拥有几个主流类型(摇滚,独立,爵士......),并有子流派映射到他们(即“摇滚”=> [“摇滚乐”,“硬石”... ])。然后,如果我们想听听摇滚类型。我想找到那种类型及其所有的子流派艺术家。
模特:
class Genre < ActiveRecord::Base
has_and_belongs_to_many :artists
has_and_belongs_to_many :parent_genres, class_name: "Genre", foreign_key: "sub_genre_id", join_table: "parent_genres_sub_genres", association_foreign_key: "parent_genre_id"
has_and_belongs_to_many :sub_genres, class_name: "Genre", foreign_key: "parent_genre_id", join_table: "parent_genres_sub_genres", association_foreign_key: "sub_genre_id"
end
create_table "parent_genres_sub_genres", id: false, force: true do |t|
t.integer "parent_genre_id"
t.integer "sub_genre_id"
end
现在真正的问题是:如何获得一系列流派的子流派列表?
我可以查询单一类型的子类型。我知道Genre.find_by(name: 'rock').sub_genres
会返回此sql以及该类型子类型的预期结果。
Genre Load (0.5ms) SELECT "genres".* FROM "genres" INNER JOIN "parent_genres_sub_genres" ON "genres"."id" = "parent_genres_sub_genres"."sub_genre_id" WHERE "parent_genres_sub_genres"."parent_genre_id" = $1 [["parent_genre_id", 13]]
我想说一句“给我所有用户指定类型(摇滚,说唱,独立,嘻哈)的子类型?但我似乎无法正确使用SQL。我想我需要某种加入,但任何帮助都会受到赞赏。
所以在下面的例子中。我可以说通过说Genre.find_by(name: 'rock').sub_genres
或Genre.find(1).sub_genres
Genre
---------
id| name
---------
1 | rock
2 | indie
3 | soul
4 | house
5 | indie pop
6 | pop
7 | stoner rock
8 | indie rock
Parent-Sub
---------
sub_genre_id | parent_genre_id
7 (stoner rock) | 1 (rock)
8 (indie rock) | 1 (rock)
8 (indie rock) | 2 (indie)
5 (indie pop) | 2 (indie)
5 (indie pop) | 6 (pop)
但是我怎样才能同时收回Rock,Pop和Indie的所有子流派? (这将是[1,2,6,5,7,8])
答案 0 :(得分:0)
我会做这样的事情:
class Genre < ActiveRecord::Base
has_and_belongs_to_many :artists
has_many :sub_genres, class_name: "Genre", foreign_key: "parent_id"
scope :parents, -> { where(parent_id: null) }
end
这样你就可以:
@roots = Genre.parents
@roots.each do |parent|
parent.sub_genres.each do |sub_genre|
puts sub_genre.id
end
end
您对HABTM协会的使用是IMO,不是必需的,因为这些类型是自我指称的
<强>祖先强>
我高度建议使用ancestry
gem进行此
这为您提供了一个框架,可以完全满足您的需求(提供父/子记录)。如果您需要(我们最近使用类别),我可以详细介绍如何使用这个宝石