rails 中的自联接返回每个预期子行的父记录

Self join in rails is returning the parent record for each expected child row

我的 rails 应用程序中有一个音频模型,它使用 id 和 parent_audio_id 字段来构建层次结构。单个音频可以是另一个音频的子音频,或者有多个子音频(我称之为派生)。

我参考了 this edge guide on self joins to construct the relationships, and this SO post to help troubleshoot

使用下面的活动记录查询,我得到了一个父音频数据重复 N 次的数据集,其中 N 等于该父项的子记录数。

如何 return 给定自连接关系的给定父音频记录的子记录?

**Audio.rb**

class Audio < ApplicationRecord

  has_many :derivatives, :class_name => "Audio", :foreign_key => "parent_audio_id"
  belongs_to :parent_audio, :class_name => "Audio", optional: true

end

**Audio Migration**
    class CreateAudios < ActiveRecord::Migration[6.0]
     def change
      create_table :audios do |t|
       t.references :parent_audio, foreign_key: {to_table: :audios}
      end
     end
    end



    **Audios Controller**
     def audio_details
      data = []
      derivatives = Audio.joins(:derivatives)
      data.push(derivatives)
      render json: data
     end

我也试过 derivatives = Derivative.joins(:audios) 但出现以下错误:

uninitialized constant Api::V1::AudiosController::Derivative

.joins 只是将 INNER JOIN 添加到查询中。它不 select 连接 table 上的任何列,也不 return 关联。它 return 是一个新的范围,基于它被调用的任何内容 - 所以在这种情况下,范围将 select 音频在加入的 table 中至少有一个匹配项(至少一个后代) .

.joins主要用于根据加入的table:

过滤记录
Patient.joins(:appointments)
       .where(scheduled_at: Time.current..)

或select聚合:

Hotel.joins(:reviews)
     .select('hotels.*', 'AVG(reviews.rating) AS average_rating')
     .group(:id)

如果你想return一个特定音频的后代你需要在class的实例上调用关联宏生成的方法:

@audio = Audio.find(params[:id])
@descendents = @audio.descendents

ActiveRecord 将自动创建一个单独的查询来加载死者。

您可以使用 .eager_load 强制执行单个查询而不是两个查询:

@audio = Audio.eager_load(:descendents)
              .find(params[:id])
@descendents = @audio.descendents

Rails Guides: Active Record Query Interface