【问题标题】:Join 3 tables on Rails在 Rails 上加入 3 个表
【发布时间】:2020-06-21 20:44:46
【问题描述】:

我有 3 张桌子:

  • 播放列表 has_many :tracks
  • 曲目 belongs_to :playlist, has_many :answers
  • 答案 belongs_to :track

一个播放列表有一个主题(不是唯一的,多个播放列表可能有相同的主题) 答案有一个状态:真或假

我想查询给定主题的真实答案。

理论上,这应该可行:

Track.joins(:answers).where(answers:{status:true}).joins(:playlist).where(playlists:{theme: myGivenTheme})

实际上,它可以在包括 .joins(:playlist) 的情况下工作,但每当我添加 where(playlists:...) 条件时都会失败。 我已经尝试过 Track.includes(:playlist) 来尝试适应 belongs_to,但也失败了,出现以下错误消息:

Track.joins(:answers).where(answers:{status:true}).joins(:playlist).where(playlist:{name:'French'}).count
 (2.1ms)  SELECT COUNT(*) FROM "tracks" INNER JOIN "answers" ON "answers"."track_id" = "tracks"."id" INNER JOIN "playlists" ON "playlists"."id" = "tracks"."playlist_id" WHERE "answers"."status" = $1 AND "playlist"."name" = $2  [["status", true], ["name", "French"]]
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "playlist"
LINE 1: ..."."playlist_id" WHERE "answers"."status" = $1 AND "playlist"...
                                                             ^
from /Users/pierre/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-6.0.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:672:in `exec_params'
Caused by PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "playlist"
LINE 1: ..."."playlist_id" WHERE "answers"."status" = $1 AND "playlist"...
                                                             ^

from /Users/pierre/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-6.0.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:672:in `exec_params'

【问题讨论】:

  • 失败怎么办?是否有错误消息或结果集与您的期望不符?
  • 我现在在主要问题上添加错误消息

标签: join activerecord ruby-on-rails-6


【解决方案1】:

我会推荐你​​原始的 sql

Track.find_by_sql('SELECT * FROM tracks t
JOIN answers a ON a.id = t.answer_id
JOIN playlist p ON p.id = t.playlist_id
WHERE status = true
AND theme = ?', myGivenTheme);

假设您使用的是列的约定

您可以选择特定的列,轨道模型上不存在的列将作为其中的一部分添加

你也可以同时加入两个表

Tracks.joins(:answers, :playlists)

我注意到您使用单数来加入 :playlist 和复数 :playlists 来表示 where

【讨论】:

  • 似乎我的联合尝试使用单数 :playlist,而复数则适用于 playlists:{theme: 'myGicenTheme'}
  • 我采用了这种方式:Track.find_by_sql('SELECT * FROM tracks t JOIN answers a ON a.id = t.answer_id JOIN playlist p ON p.id = t.playlist_id WHERE status = true AND theme = ?', 'French'); 他返回 NoMethodError: undefined method `map' for "French":String,这很奇怪。如果我做同样的事情 ``a.statusand p.theme```
  • Track.joins(answers: :playlists) 是第一次尝试,但返回 ActiveRecord::ConfigurationError: Can't join 'Answer' to association named 'playlists';也许你拼错了?来自 /Users/pierre/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-6.0.2.1/lib/active_record/associations/join_dependency.rb:192:in `find_reflection'
【解决方案2】:

我终于解决了我的问题,希望这对我没有找到很多关于这个特定语法主题的文档有所帮助。正确的查询,用于查找整个用户的正确答案 (answer.status = true),对于给定的播放列表主题,名为 myGivenTheme 和给定的 user强>,是:

Playlist.where(theme: myGivenTheme).joins(tracks: :answers).where(answers:{status: true, user_id: self.id})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    相关资源
    最近更新 更多