【问题标题】:trouble querying has and belongs to many self join with rails activerecord问题查询具有并且属于许多使用 rails activerecord 的自联接
【发布时间】:2014-02-14 20:10:16
【问题描述】:

我正在尝试查询 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 来说让我摇滚和所有它的子流派并让这些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)

但我如何才能同时恢复摇滚、流行和独立的所有子类型? (这将是 [1, 2, 6, 5, 7, 8])

【问题讨论】:

  • SHOW CREATE,样本数据和想要的输出示例

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


【解决方案1】:

我会这样做:

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

IMO 不需要您使用 HABTM 关联,​​因为类型是自我参照的


祖先

我会强烈建议为此使用ancestry gem

这为您提供了一个框架,可以完全满足您的需求(提供父/子记录)。如果您需要,我可以详细说明如何使用此 gem(我们最近已将其与类别一起使用)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多