基于以下内容,我想基于artist
及其artist_credit
查询相册。 artist_credit
关联是多态的,可以属于发行版或曲目。这使我无法进行HMT。我可以通过在查询中包含一个内容来从曲目方面抓取专辑:
Album.includes(tracks: :artist_credits).where(artist_credits: { id: artist_id })
但是我想做的是同时掌握两个曲目的和版本。我想到要使用or
子句,但会收到此错误:
ArgumentError (Relation passed to #or must be structurally compatible. Incompatible values: [:includes])
尝试此操作时:
Album.includes([tracks: :artist_credits, releases: :artist_credits]).where(artist_credits: { id: artist_id }).or(where(artist_credits: { id: artist_id }))
我该如何使用它?还有更好的方法吗?
class Album < ApplicationRecord
has_many :releases, dependent: :destroy
has_many :tracks, dependent: :destroy
has_many :album_artists, dependent: :destroy
has_many :artists, through: :album_artists
end
class Track < ApplicationRecord
has_many :artist_credits, as: :creditable, dependent: :destroy
belongs_to :album
end
class Release < ApplicationRecord
has_many :artist_credits, as: :creditable, dependent: :destroy
belongs_to :album
end
class ArtistCredit < ApplicationRecord
belongs_to :artist
belongs_to :creditable, polymorphic: true # release or track
end
答案 0 :(得分:1)
我建议以下
class Album < ApplicationRecord
scope :accredited_artist, ->(artist_id) {
includes([tracks: :artist_credits, releases: :artist_credits])
.where(id:
where(
id: Track.accredited_artist(artist_id).select(:album_id)
).or(
where(
id: Release.accredited_artist(artist_id).select(:album_id)
)
)
)
}
end
class Track < ApplicationRecord
scope :accredited_artist, ->(artist_id) {
joins(:artist_credits).where(artist_credits: { id: artist_id })
}
end
class Release < ApplicationRecord
scope :accredited_artist, ->(artist_id) {
joins(:artist_credits).where(artist_credits: { id: artist_id })
}
end
从理论上讲,这应该导致查询类似于
SELECT
albums.*
FROM
albums
WHERE
albums.id IN (
SELECT
albums.id
FROM
albums
WHERE
albums.id IN (
SELECT
tracks.album_id
FROM
tracks
INNER JOIN artist_credits ON [whatever your join is here]
WHERE
artist_credits.artist_id = [ID]) OR
albums.id IN (
SELECT
releases.album_id
FROM
releases
INNER JOIN artist_credits ON [whatever your join is here]
WHERE
artist_credits.artist_id = [ID])
)