4

In my Rails app, projects can have videos. I want to create a scope for the Project to grab projects that do not have a video associated with it. How do I do this?

Here are my model associations

class Project < ActiveRecord::Base
  has_one :video
end

class Video < ActiveRecord::Base
    belongs_to :project
end
scientiffic
  • 9,045
  • 18
  • 76
  • 149

5 Answers5

6

Just faced this right now, and this has worked for me:

Project.includes(:video).where(videos: { id: nil })

The trick is to use the singular in includes and the plural in where

3

building off of messanjah's answer, the way you would turn that into a scope is the following:

class Project < ActiveRecord::Base
  has_one :video
  scope :videoless, -> { left_joins(:videos).where("videos.id IS NULL") }
end

class Video < ActiveRecord::Base
  belongs_to :project
end
ian root
  • 349
  • 1
  • 11
1

Use a LEFT join and select out rows where the joined id is null.

Project.joins("LEFT JOIN videos ON videos.project_id = projects.id").
  where("videos.id IS NULL")
messanjah
  • 8,977
  • 4
  • 27
  • 40
0

I assume this should work: Project.where.not(id: Video.select(:project_id).uniq). Maybe you don't need uniq if a project has one unique video.

peresleguine
  • 2,343
  • 2
  • 31
  • 34
0

You should try this Project.joins(:video).where('videos.id IS NULL')

  • This will always return an empty set because joins(:video) uses an INNER join on videos.id, so "videos.id IS NULL" will not match any records. – messanjah Apr 19 '15 at 16:19