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!
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.