0

在我的应用程序中,我的模型定义了和Sinatra之间的 HABTM 关系。我正在尝试定义几个范围,一个用于所有与 no call 相关联的范围,一个返回所有被特定的“未读”的范围。UsersNotificationsNotificationsUsersunreadNotificationsUser

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
  }

范围工作正常,unreadunread_by范围没有给我预期的结果。

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

我怀疑我的查询逻辑有缺陷,但我已经盯着这个太久了,我只是没有看到它。我错过了什么?

4

2 回答 2

0

好的,这解决了它,但它对我来说似乎不是超级优雅。

scope :unread_by, ->(u){
  Notification.joins("LEFT JOIN notifications_users ON notifications.id = notifications_users.notification_id").
                where("notifications_users.user_id <> ? OR notifications_users.user_id IS NULL", u.id).uniq
}

它虽然有效。耶 - 谢谢大家的帮助,它为我指明了正确的方向。

于 2013-09-05T23:21:11.223 回答
0

对于 ActiveRecord 4,您应该在范围块内使用新样式的查询界面

http://guides.rubyonrails.org/active_record_querying.html

完全未经测试,但以下应该是如何构建查询的指南:(请注意,每个方法都链接到它上面的那个)

scope :unread, {
    joins( "LEFT JOIN notifications_users ON notifications.id = notifications_users.notification_id").
    where("notifications_users.user_id IS NULL").
    select("DISTINCT notifications.*")
}

scope :unread_by, ->(u){
    joins("LEFT JOIN notifications_users ON notifications.id = notifications_users.notification_id").
    where(["notifications_users.user_id IS ?", u.id]).
    select("DISTINCT notifications.*")
}
于 2013-09-05T07:38:40.997 回答