麻烦查询已经并且属于许多自我加入rails activerecord

时间:2014-02-14 20:10:16

标签: sql ruby-on-rails ruby activerecord ruby-on-rails-4

我正在尝试查询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_genresGenre.find(1).sub_genres

来获取Rock和它的所有子类并获得这些ID [1,7,8]
    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])

1 个答案:

答案 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进行此

这为您提供了一个框架,可以完全满足您的需求(提供父/子记录)。如果您需要(我们最近使用类别),我可以详细介绍如何使用这个宝石