Использование или предложение с включает - PullRequest
0 голосов
/ 03 мая 2019

Исходя из следующего, я бы хотел запросить альбомы на основе 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

1 Ответ

1 голос
/ 03 мая 2019

Я бы порекомендовал следующее

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])
  )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...