1

We have images on our site which users can select as profile images for their accounts. Here are the relevant lines in the models:

class User < ApplicationRecord
  has_one :profile_image, dependent: :destroy
  has_one :image, through: :profile_images
  accepts_nested_attributes_for :profile_image, allow_destroy: true
end

class Image < ApplicationRecord
 has_many :profile_images, dependent: :destroy
  has_many :users, through: :profile_images
end

class ProfileImage < ApplicationRecord
  belongs_to :image
  belongs_to :user
  validates  :user_id,  presence: true, allow_nil: false, uniqueness: true
  validates  :image_id, presence: true, allow_nil: false
end

I'd like to add an option to the User index view to only show Users with profile images. I'm searching with where.not(profile_image: nil) in the controller, but I just get all users back.

In the console, I can confirm that I have users with and without profile images:

>> User.first.profile_image
=> nil
>> User.second.profile_image
=> #<ProfileImage id: 2, image_id: 9, user_id: 6, created_at: "2019-10-26 17:52:37", updated_at: "2019-10-26 17:52:37">

But I get the same totals from User.all.count and User.where.not(profile_image: nil).count.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Jeff Covey
  • 55
  • 5
  • the through: functionality, as I understand it, is intended for many to many relationships. IOW, it's a join table with added attributes. It's a model with join table behavior. So you might change the has_one to has_many (even though there is only one) or try to create this relationship in a different way. I'm no expert and would like to hear from others as well. – user13025904 Mar 08 '20 at 02:13

3 Answers3

0

I think this should work:

User.joins(:profile_image)

Per default joins generates an INNER JOIN SQL query in Ruby on Rails. That means it will only return records that have associated records in the other table.

This default can be used in this case because the fact that a user has no profile image means that there will be no profile_image associated with that user.

spickermann
  • 100,941
  • 9
  • 101
  • 131
0

has_one does not have an image id stored on users table. Hence, your original query is irrational.

So, based on your description, I would suggest counting the images (has_one means that each image belongs to one user)

ProfileImage.count

Seems too simple to be true, doesn't it?

Ruby Racer
  • 5,690
  • 1
  • 26
  • 43
  • Thanks, Racer! But I need to use the returned records in a view, so just getting a count of them doesn’t help. – Jeff Covey Mar 08 '20 at 14:19
-1

Install and use where_exist gem

gem 'where_exists'

User.where_exists(:profile_image)
Bodh1004
  • 309
  • 3
  • 9