Насколько я понимаю ваш вопрос, вы хотите найти все альбомы, в которых нет трека с отсутствующим (пустым) идентификатором youtube-uid. Итак, вам нужен запрос NOT EXISTS
.
В sql я бы написал что-то вроде
select * from albums a
where not exists (select * from tracks where album_id = a.id and youtube_uid is null)
Итак, как нам лучше всего перевести это в activerecord? Я вижу две возможности:
sql = <<-SQL
select * from albums a
where not exists (select * from tracks where album_id = a.id and youtube_uid is null)
SQL
Album.find_by_sql(sql)
в то время как это работает, и для меня, как дома в SQL, это нормально, это не очень похоже на рельсы, так что мы можем это улучшить?
Есть более короткая форма:
Album.where("not exists (select * from tracks where album_id = albums.id and youtube_uid is null")
но это все еще кажется слишком многословным. К счастью, существует более рельсовый способ. В рельсах 4 вы можете написать:
Album.where(Track.where("album_id = albums.id").where(youtube_uid: nil).exists.not)
В рельсах 5/6 это уже невозможно, и вы должны написать:
Album.where(Track.where("album_id = albums.id").where(youtube_uid: nil).arel.exists.not)
вы можете легко убедиться, что это генерирует хороший sql, добавив to_sql
в конце.
person
nathanvda
schedule
26.08.2020
WHERE NOT EXISTS(SELECT 1 FROM tracks WHERE tracks.youtube_uid IS NULL AND tracks.album_id = album.id)
. - person max   schedule 26.08.2020PG::SyntaxError: ERROR: syntax error at or near "WHERE" (ActiveRecord::StatementInvalid) LINE 1: SELECT "albums".* FROM "albums" WHERE (WHERE NOT EXISTS(SELE...
- person Carl Edwards   schedule 26.08.2020