Rails - has_one relation: areas for related and unrelated objects

I have this attitude: the user may have zero or one dog, but the dog must belong to someone.

# dog.rb class Dog < ActiveRecord::Base belongs_to :user end # user.rb class User < ActiveRecord::Base has_one :dog end 

I want to identify the following areas:

 User.with_a_dog User.without_a_dog 

I can do this for the first case, because the default connections are INNER JOIN in rails:

 scope :with_a_dog, :joins(:dog) 

1 / Is this solution for the first area good enough?

2 / What would you do for the second?

3 / (A bit related) Is there a better way to do this?

 # user.rb def has_a_dog? !self.dog.nil? end 

Thank you for your help!

+4
source share
3 answers

To question 2, I think the following should work:

 scope :without_a_dog include(:dog), where('dogs.id is null') 

In the case where include should make a left join, means that where there is no dog relationship to the user connection, the dogs.id column should be zero.

+1
source

Just wanted to add this if someone finds this useful:

user.rb

 class User < ActiveRecord::Base has_one :dog # To get records with a dog we just need to do a join. # AR will do an inner join, so only return records with dogs scope :with_a_dog, -> { joins(:dog) } # To get records without a dog, we can do a left outer join, and then only # select records without a dog (the dog id will be blank). # The merge with the Dog query ensures that the id column is correctly # scoped to the dogs table scope :without_a_dog, -> { includes(:dog).merge( Dog.where(:id => nil) ) } end 

dog.rb

 class Dog < ActiveRecord::Base belongs_to :user end 
+4
source

user.rb

 scope :without_a_dog, -> { includes(:dog).select { |user| user.dog.nil? } } 
+1
source

All Articles