Search code examples
ruby-on-railsrubyruby-on-rails-3ruby-on-rails-4ruby-on-rails-5

ruby on rails: list records that does not match a given set of ids


So, I have three models:

class Restaurant < ActiveRecord::Base
  has_many :reviews
  has_many :users, through: :reviews
end

class Review < ActiveRecord::Base
  belongs_to :restaurant
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :reviews
  has_many :restaurants, through: :reviews
end

Now, if I want to list all restaurants reviewed by @user I just need:

Restaurant.joins(:reviews).where("reviews.user_id": @user.id)

Fine. But what if I want to list all restaurants not reviewed by @user? I tried this:

Restaurant.joins(:reviews).where.not(“reviews.user_id": @user.id)

Unfortunately this doesn’t work, as it will also return those restaurants reviewed by @user that have been reviewed by other users!

I came up with this horrible and expensive hack:

Restaurant.joins(:reviews).reject {|x| x.users.where(id: @user.id).present? }

I’m sure there MUST be a better way. HELP!


Solution

  • It's pretty easy.

    You have to map the ids of all restaurants reviewed by @user

    reviewed_restaurants = Restaurant.joins(:reviews).where("reviews.user_id": @user.id).map(&:id)
    

    Then fire another query to fetch restaurants other than those selected before

    @unreviewed_restaurants = Restaurant.where("id not in (?)", reviewed_restaurants)
    

    Hope it works for you.