Jason
Jason

Reputation: 1129

Testing if object exists in joined ActiveRecord query

I have User model that is related to a Friend model (has_many / belongs_to)

After joining, I would like to be able to check if a certain friend object exists in the friends that were joined to users:

users = User.joins(:friends).where("some condition")    # subset of total friends
fs = Friend.all
fs.each do |f|
  if users.friends.includes?(f) # match!
     ...
  else   # no match
     ...
end

The code as-is does not work and I am having difficulties getting this functionality in code.

Upvotes: 1

Views: 1359

Answers (1)

Paul Richter
Paul Richter

Reputation: 11072

Try something like this:

users.friends.where(id: u.id).exists?

That should generate a query like so:

SELECT 1 AS one FROM `users` WHERE `users`.`friend_id` = 42 AND `users`.`id` = 1 LIMIT 1

You'll either get back the number 1 (considered "truthy"), or nil (considered "falsey").

Side note: Unless you need to use your u variable later, you can probably get away with simply placing some_id directly in the where clause, and not do the second User lookup.

Edit

Just noticed a problem in your loop that might be what is causing your original problem. When you loaded up the list of users, unless you have some limit clause or invoked .first, you'll get back an array of users. So I'm guessing your application is crapping out on this line:

users.friends.includes?(f)

Because .friends is a method of a User object, not of an array.

So you'll have to do a nested loop instead like so:

fs.each do |f|
    users.each do |u|
        u.friends.includes?(f)
    end
end

Note that this method might be very slow, depending on the number of friends and users. It is a very inefficient algorithm, which is why I'm trying to understand your situation better in the comments, because I'm certain there's a more efficient way to accomplish your task.

Upvotes: 1

Related Questions