【问题标题】:How to find a record through an association?如何通过关联查找记录?
【发布时间】:2020-07-13 17:21:58
【问题描述】:

有四个表 - chat_roomschat_messageschat_rooms_and_usersusers

  • chat_rooms - 房间有消息和用户。
  • chat_rooms_and_users - 通过这个表,用户可以连接到房间。

每个房间可以有两个用户。

如何找到认识两个用户的房间?

我试过这样:

room = joins(:chat_rooms_and_users)
       .find_by(
         type: ChatRoom.types[:private],
         chat_rooms_and_users: {
           user: [user_a, user_b]
         }
       )
SELECT "chat_rooms".* FROM "chat_rooms" INNER JOIN "chat_rooms_and_users" ON "chat_rooms_and_users"."room_id" = "chat_rooms"."id" WHERE "chat_rooms"."type" = $1 AND "chat_rooms_and_users"."user_id" IN ($2, $3) LIMIT $4  [["type", 0], ["user_id", 497], ["user_id", 494], ["LIMIT", 1]]

这在 SQL 代码中困扰着我:

"chat_rooms_and_users"."room_id" = "chat_rooms"."id"

如果没有房间,则正常创建第一个房间。但是总是只有 ID 比其他房间在前的房间。

【问题讨论】:

    标签: ruby-on-rails activerecord ruby-on-rails-6


    【解决方案1】:

    您的问题是"chat_rooms_and_users"."user_id" IN ($2, $3) 将返回任何一个用户在场的所有“私人”房间。

    相反,您想找到一个两者都存在的聊天室。 我建议为此制定一个范围

    #assumed 
    class User < ApplicationRecord
      has_many :chat_rooms_and_users
    end
    
    class ChatRoom < ApplicationRecord 
     
      scope :private_by_users, ->(user_a,user_b) { 
          where(type: ChatRoom.types[:private])
          .where(id: user_a.chat_rooms_and_users.select(:chat_room_id))
          .where(id: user_b.chat_rooms_and_users.select(:chat_room_id))
       }
    end 
    
    #Then 
    ChatRoom.private_by_users(user_a,user_b)
    

    这将返回user_auser_b 都是参与者的“私人”房间集合。 SQL 将类似于:

    SELECT "chat_rooms".* 
    FROM "chat_rooms" 
    WHERE "chat_rooms"."type" = 0 AND 
     "chat_rooms"."id" IN ( 
        SELECT 
          "chat_rooms_and_users"."chat_room_id" 
        FROM  
          "chat_rooms_and_users"
        WHERE 
          "chat_rooms_and_users"."user_id" = user_a_id
      ) AND "chat_rooms"."id" IN ( 
        SELECT 
          "chat_rooms_and_users"."chat_room_id" 
        FROM  
          "chat_rooms_and_users"
        WHERE 
          "chat_rooms_and_users"."user_id" = user_b_id
      )
    

    如果您可以保证只有 1 个或 0 个此类房间,并且有两个参与者,那么您可以将 first 添加到此链的末尾。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-21
      • 1970-01-01
      • 1970-01-01
      • 2016-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多