2015-05-30 43 views
0

我正在實施聊天室數據結構。如何找到兩個用戶的房間

room.rb

class Room < ActiveRecord::Base 
    has_many :room_user_ships 
    has_many :users, through: :room_user_ships 
end 

room_user_ship.rb

class RoomUserShip < ActiveRecord::Base 
    belongs_to :room 
    belongs_to :user 
end 

user.rb

class User < ActiveRecord::Base 
    has_many :room_user_ships 
    has_many :rooms, through: :room_user_ships 
end 

schema.rb

create_table "rooms", force: true do |t| 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 
create_table "room_user_ships", force: true do |t| 
    t.integer "room_id" 
    t.integer "user_id" 
end 
create_table "users", force: true do |t| 
    t.string "name" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
end 

我能得到用戶的房間和房間的用戶

room = Room.find(100) 
room.users 

我的問題是,當用戶亞歷克斯(用戶ID:10001)將消息發送給用戶艾瑪(用戶ID:10002),我一定要找到房間這些用戶的ID,但我不知道該怎麼做。

迭代所有房間的作品,但不是一個好主意。

user = User.find(10001) 
receiver = User.find(10002) 
user.rooms.each do |room| 
    if room.users.include?(receiver) 
    the_room = room # find it! 
    break 
    end 
end 
+1

另一種方法是使用collect'user.rooms.collect {| room |房間,如果room.users.include?(接收器)}' –

回答

2

假設你已經擁有了2個用戶,那是這樣的:

room = Room.joins(:room_user_ships) \ 
      .where(room_user_ships: { user_id: [user.id, receiver.id] }) \ 
      .where(room_user_ships: { room_id: user.room_ids }).first 
+0

它的工作原理,謝謝! – Howard

+0

這真的是對的嗎?第一個'where'從用戶或接收者中選擇所有具有room_user_ships的房間(該數組轉換爲SQL IN運算符),第二個'where'基本上將此集合減少到用戶的房間。所以我認爲這個聲明有時會返回沒有連接到接收器的房間。 – Meier

0

ActiveRecord的joins()方法可以讓您根據連接的對象條件找對象。因爲用戶和接收器都有自己的RoomUserShip,所以它變得更復雜一些。所以你需要用同一張桌子連接兩次。我想,你可以利用加入由User.rooms關係產生的隱性的,所以希望這將工作:

user.rooms. 
    joins(:room_user_ships). 
    where(room_user_ships: {user_id: receiver.id}).first 

看一看它的ActiveRecord生成的SQL。它應該有兩個不同的連接。

+0

你的答案有語法錯誤,應該是'user.rooms.joins(:room_user_ships).where(room_user_ships:{user_id:receiver.id}).first'。但是,當我運行這個時,我得到零。生成SQL:'房間加載(1.6ms)SELECT「房間」* FROM「房間」INNER JOIN「room_user_ships」「room_user_ships_rooms」ON「room_user_ships_rooms」。「room_id」=「rooms」。「id」INNER JOIN「room_user_ships」ON 「房間」。「id」=「room_user_ships」。「room_id」WHERE「room_user_ships」。「user_id」= $ 1 AND「room_user_ships」。「user_id」= 10002 ORDER BY「rooms」。「id」ASC LIMIT 1 [[「 user_id「,10001]]' – Howard

+0

@楊萬皇我問作者.. :) –

+0

ActiveRecord似乎沒有區分兩個連接之間的關係。 where子句是錯誤的:WHERE「room_user_ships」。「user_id」= $ 1 AND「room_user_ships」。「user_id」= 10002 以$ 1作爲10001,這當然會讓我們爲零。在SQL中,我會使用賦予表的別名與AS。我不知道如何用ActiveRecord來做到這一點。 – Meier

相關問題