Rails基于缺少具有条件的关联模型来查询一个模型

时间:2013-02-26 22:09:19

标签: mysql sql ruby-on-rails database ruby-on-rails-3

我总是遇到一个基于多个关联模型查询的问题,并且基于缺少关联模型进行查询。

所以我正在尝试实现一种方法,将消息标记为是否为每个特定用户读取。这些是我正在使用的模型:

class Stock < ActiveRecord::Base
  has_many :messages
end

class Message < ActiveRecord::Base
  belongs_to :stock
  has_many :message_viewings
end

class MessageViewing < ActiveRecord::Base
  belongs_to :user
  belongs_to :message
end

class User < ActiveRecord::Base
  has_many :message_viewings
end

我的目标是找到特定用户缺少MessageViewings的所有Stocks。我想要这些信息,以便我可以向用户表明他们是否有未读消息。到目前为止,我的所有尝试都没有值得一提。

更新

进一步的搜索使我得到了一个很好地记录的宝石,它几乎完成了我想要的东西:https://github.com/ledermann/unread。根据那里列出的查询并稍微修改它我已经来到这个新的查询,这似乎得到了我想做的事情,虽然我不确定它可能有多高效:

Stock.joins(:messages).joins("LEFT JOIN message_viewings ON \
  message_viewings.message_id = messages.id AND \
  message_viewings.user_id = #{User.sanitize(current_user.id)}").where(
  "message_viewings.id IS NULL")

1 个答案:

答案 0 :(得分:0)

尝试类似:

Stock.joins(messages: :message_viewings).where("message_viewings.user_id != ? or message_viewings.user_id is null", current_user.id)

只需确保当前用户已设置。

更新的代码

如果您希望所有没有message_viewing的股票属于当前用户,请执行以下操作:

@user = # code to retrieve user
Stock.joins(:messages).joins("LEFT JOIN message_viewings ON message_viewings.message_id = messages.id").where("message_viewings.user_id != ? OR message_viewings.id IS NULL", @user.id)

我认为您编写的代码存在错误,因为如果message_viewing中的user_id存在,那么message_viewing的id将不会为null。

我可能会将该代码放入库存模型中:

# stock model
def self.join_message_viewings
  joins(:messages).joins("LEFT JOIN ... ")
end

def self.unread_by(user_id)
  .where("messages_viewings.user_id != ... ", user_id)
end

# query
Stock.join_message_viewings.unread_by(@user.id)

如果您愿意,可以将最终查询转换为一种方法。