Friday, March 18, 2016

find all that are nil in the association in ruby on rails

Leave a Comment

Here I've got a 1-to-many relationship between Products and Users:

class Property < ActiveRecord::Base   has_many :users end  class User < ActiveRecord::Base   belongs_to :property end 

How could I get all the properties which do not belong to any user?

6 Answers

Answers 1

To get all properties that have no user, try this:

Property.includes(:users).where(users: { property_id: nil }) 

Answers 2

You can try this query:

Property.where.not(:id=>User.where.not(:property_id=>nil).pluck(:property_id)) 

or

 Property.where.not(:id=>User.where.not(:property_id=>nil).pluck("DISTINCT property_id")) 

Answers 3

One more approach would be to write some SQL:

Property.joins("LEFT OUTER JOIN users ON users.property_id = properties.id"). where('users.id IS NULL'). uniq 

The code above is being translated to the following pure SQL query to the database:

SELECT DISTINCT properties.* FROM properties  LEFT OUTER JOIN users on users.property_id = properties.id  WHERE users.id IS NULL; 

LEFT JOIN keyword returns all rows from the left table (properties), with the matching rows in the right table (users). The result is NULL in the right side when there is no match. Afterwards WHERE keyword filters results by a condition that we're intrested in those rows which have NULL on the right side only.

Left outer join with WHERE NULL

Reference: SQL LEFT JOIN Keyword

Answers 4

You can do it like this too:

Property.where('id NOT IN (SELECT DISTINCT(property_id) FROM users)') 

Another option would be:

Property.where("(select count(*) from users where property_id = properties.id) = 0") 

You can always check which is more efficient according to you application by checking the time take to execute the queries and choose an option accordingly.

Answers 5

use this code:

@users= User.includes(:properties).where(properties: { property_id: nil }) 

Answers 6

Also You can write scope based on this query just for easy use.

class Property < ActiveRecord::Base   has_many :users   scope :incomplete, -> { joins(:users).where("property.user_id is null") } end 

Then, You can call this scope like this: Property.incomplete

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment