In my Sinatra app my model defines a HABTM relationship between Users and Notifications. I am trying to define a couple of scopes, one for all Notifications associated with no Users called unread and one that returns all Notifications that are 'unread' by a particular User.
class Notification < ActiveRecord::Base
  has_and_belongs_to_many :users
  scope :unread, ->{
    Notification.joins("LEFT JOIN notifications_users ON notifications.id = notifications_users.notification_id").
                  where("notifications_users.user_id IS NULL").uniq
  }
  scope :unread_by, ->(u){
    Notification.joins("LEFT JOIN notifications_users ON notifications.id = notifications_users.notification_id").
                  where("notifications_users.user_id <> ?", u.id).uniq
  }
The unread scope works fine but the unread_by scope is not giving me the results I expect.
it "should know which notifications have not yet been read by anyone, or by a particular user" do
  n1 = Notification.create!(title: 'test 1', text: 'this is some longer text about the notification')
  n2 = Notification.create!(title: 'test 2', text: 'this is also some longer text about the notification')
  Notification.unread.must_include(n1)
  Notification.unread.must_include(n2)
  @user1.read(n1)
  Notification.unread.wont_include(n1)
  Notification.unread.must_include(n2)
  Notification.unread_by(@user1).wont_include(n1)
  Notification.unread_by(@user1).must_include(n2) # => fails
  Notification.unread_by(@user2).must_include(n1)
  Notification.unread_by(@user2).must_include(n2) # => fails
end
I suspect my query logic is flawed but I've been staring at this for too long and I'm just not seeing it. What am I missing?
                        
Okay this fixed it, but it doesn't seem super-elegant to me.
It works though. Yay - Thanks all for your help, it pointed me in the right direction.