【问题标题】:How do I call a join table in my show method? UPDATED如何在我的 show 方法中调用连接表?更新
【发布时间】:2021-01-13 12:12:30
【问题描述】:

[更新,向下滚动查看解决方案]

我正忙于使用 Rails 开发音乐流媒体应用程序,但遇到了一个基本问题。我不知道如何调用我的联合表。

这是我的流程:

  • 用户有很多播放列表 > 一个播放列表有很多曲目 > 一个曲目可以 属于许多播放列表
  • 现在,用户可以创建播放列表,用户可以查看索引 播放列表
  • 问题 >> 用户看不到播放列表中的曲目

我有 3 个与播放列表和曲目相关的表格

create_table "tracks", force: :cascade do |t|
    t.string "title"
    t.text "description"
    t.string "artist"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.bigint "album_id", null: false
    t.bigint "user_id", null: false
    t.string "photo"
    t.string "track"
    t.index ["album_id"], name: "index_tracks_on_album_id"
    t.index ["user_id"], name: "index_tracks_on_user_id"
  end

create_table "playlists", force: :cascade do |t|
    t.string "playlist_title"
    t.text "playlist_description"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.bigint "user_id", null: false
    t.index ["user_id"], name: "index_playlists_on_user_id"
  end

create_table "playlists_tracks", id: false, force: :cascade do |t|
    t.bigint "playlist_id", null: false
    t.bigint "track_id", null: false
  end

期望的结果 -> 在 Show.html.erb 中渲染曲目,其中曲目的 playlist_id 为 x

我当前的代码在我的 playlists_controller.rb 中看起来像这样

def show
    @playlist = Playlist.find(params[:id])
    @track = Track.where(playlist_id: params[:id])
end

结果是错误提示

column tracks.playlist_id does not exist
LINE 1: SELECT "tracks".* FROM "tracks" WHERE "tracks"."playlist_id"...

如果我在架构中访问我的曲目表,它找不到 playlist_id 值是有道理的,因为该表没有 playlist_id 列。

但是,我的 playlists_tracks 联合表中有一个 playlist_id 和一个 track_id。

不明白的地方>>

当用户添加曲目时,我知道曲目信息正在添加到曲目表中。但是没有添加到 playlists_tracks 表的信息。我期望当用户将曲目添加到播放列表时,这是现有曲目将与一个/许多播放列表相关联的时候。我还没有创建将曲目添加到播放列表的函数。

现在我只是尝试查看特定播放列表的 SHOW 页面,其中包含将呈现相关曲目的代码。我当前的代码在曲目表中找不到 playlist_id,因为它不存在。我的第一个想法是更改我的 SHOW 方法,以便它搜索 playlists_tracks 表而不是 track 表。

但是,我的语法没有意义。我应该像下面这样调用我的 playlists_tracks 表吗?用大写字母 P 和单数轨道?

新的展示方式:

def show
        @playlist = Playlist.find(params[:id])
        @playlist_track = Playlists_track.where(playlist_id: params[:id])
    end

希望我的描述能有所帮助,而不是矫枉过正! 感谢您的宝贵时间。

为了进一步参考,这里是我的关联模型

class Playlist < ApplicationRecord
    has_many :tracks, through: :playlists_tracks
    has_many :tags, through: :playlists_tags
    belongs_to :user

    validates :playlist_title, presence: true, length: { in: 1..20 }
    validates :playlist_description, presence: true, length: { in: 10..60 }

    has_one_attached :photo
end

class Track < ApplicationRecord
    belongs_to :album
    belongs_to :user
    has_many :playlists, through: :playlists_tracks
    has_many :tags, through: :tags_tracks

    validates :title, presence: true, length: { in: 1..20 }
    validates :description, presence: true, length: { in: 10..60 }
    has_one_attached :photo
    has_one_attached :track
end

[更新]

  1. 我缺少一个 PlaylistTrack 模型
  2. 我的 has_many 关联需要更正
  3. 播放列表控制器显示方法已更改语法

新型号

class PlaylistTrack < ApplicationRecord
belongs_to :track
belongs_to :playlist
end

添加到架构

  create_table "playlist_tracks", force: :cascade do |t|
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.bigint "playlist_id", null: false
    t.bigint "track_id", null: false
    t.index ["playlist_id"], name: "index_playlist_tracks_on_playlist_id"
    t.index ["track_id"], name: "index_playlist_tracks_on_track_id"
  end

更正的播放列表模型

class Playlist < ApplicationRecord
    has_many :playlist_tracks
    has_many :tracks, through: :playlist_tracks
    has_many :tags, through: :playlist_tags
    belongs_to :user

    validates :playlist_title, presence: true, length: { in: 1..20 }
    validates :playlist_description, presence: true, length: { in: 10..60 }

    has_one_attached :photo
end

修正轨道模型

class Track < ApplicationRecord
    belongs_to :album
    belongs_to :user
    has_many :playlist_tracks
    has_many :playlists, through: :playlist_tracks
    has_many :tags, through: :tags_tracks

    validates :title, presence: true, length: { in: 1..20 }
    validates :description, presence: true, length: { in: 10..60 }
    has_one_attached :photo
    has_one_attached :track
end

更正显示方法

def show
    @playlist = Playlist.find(params[:id])
    @tracks = @playlist.tracks
end

连接具有 N:N 关系的表非常令人困惑。我预计会出现更多错误,因为我在控制台中的测试并不乐观(播种带有曲目的播放列表),但至少播放列表显示页面现在正在呈现。

希望对您有所帮助,如果您有任何建议,请在下方留下:)

【问题讨论】:

标签: ruby ruby-on-rails-5 audio-player playlist audiotrack


【解决方案1】:

创建包含代码 sn-ps 的答案: 我将假设“playlist_tracks”表是使用foreign keys/references 创建到它所连接的相关表的:

class CreatePlaylistTracks < ActiveRecord::Migration[6.0]
  def change
    create_table :playlist_tracks do |t|
      t.references :playlist, null: false, foreign_key: true
      t.references :track, null: false, foreign_key: true

      t.timestamps
    end
  end
end

您需要调整模型(还假设您定义了 PlaylistTrack 模型,其中包含 belongs_tos):

class Playlist < ApplicationRecord
    has_many :playlist_tracks, inverse_of: :playlist
    has_many :tracks, through: :playlist_tracks
    has_many :tags, through: :playlist_tags
    belongs_to :user

    validates :playlist_title, presence: true, length: { in: 1..20 }
    validates :playlist_description, presence: true, length: { in: 10..60 }

    has_one_attached :photo
end

然后在控制器中,你应该能够做到:

def show
    @playlist = Playlist.find(params[:id])
    @track = @playlist.tracks
end

你能看出这有什么不同吗?

【讨论】:

  • 应用您的建议后,我收到一条错误消息:在模型播放列表中找不到关联:playlists_tracks。此外,我的迁移文件看起来有点不同。我目前没有 PlaylistTrack 模型,并且认为我需要将其与其关联添加才能继续。当我进行更改但仍然遇到相同的问题时会更新
  • 应该是:playlist_tracks ...只有最后一个词应该是复数形式
  • 您能否在问题中包含PlaylistTrack 的模型?如果需要调整,我可以更新我的答案
  • 所以你的建议很接近!我创建了一个新模型 PlaylistTrack 并添加了 belongs_to :track、belongs_to :playlist,它在带有 playlist_id 和 track_id 的模式中创建了一个新表。然后我需要在我的 Track 模型和 Playlist 模型中纠正我的 has_many。会更新我的帖子
  • 我猜你也需要考虑用 :playlist_tags 做同样的事情,但希望我们能让你走上正轨
【解决方案2】:

期望的结果 -> 在 Show.html.erb 中渲染曲目,其中曲目的 playlist_id 为 x

def show
    @playlist = Playlist.find(params[:id])
    @tracks = @playlist.tracks
end

如果只需要轨道,另一种解决方案:

def show
  @tracks = Track.includes(:playlists).where(playlists: { id: params[:id] })
end

【讨论】:

  • 谢谢Rastagot,已经搞定了
猜你喜欢
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-20
  • 1970-01-01
相关资源
最近更新 更多