Rails 4 Conversation Model JOIN表,条件为

时间:2015-12-17 19:04:26

标签: ruby-on-rails postgresql ruby-on-rails-4 join

我有对话模型

recipient_id
sender_id

获取当前用户的对话看起来像

conversations = Conversation.where("conversations.sender_id =? OR conversations.recipient_id =?",current_user.id,current_user.id)

让我们在会话中呼叫 other_user 非当前用户。

由于当前用户可以是发件人或收件人,因此无法在users表上使用JOIN或Include来获取对话中涉及的“其他用户”。因此,呈现对话会创建N + 1情况,为每个其他用户发出1个查询。

有没有办法使用includes或JOIN获取other_user,条件基本上是:

if current_user_id == recipient_id JOIN on recipient_id
if current_user_id == sender_id JOIN on sender_id

1 个答案:

答案 0 :(得分:1)

如果你只需要other_user的某些属性,比如用户名,那么这样的东西应该有效:

conversations = Conversation.find_by_sql([<<-SQL, current_user.id, current_user.id, current_user.id])
  SELECT
    convos_involving_user.*
  FROM
    -- We'll use UNION to create a table that joins together the users and
    -- conversations tables based on both sender and recipient. Each
    -- conversation will be represented by two rows in this joined table:
    -- one row joining that conversation to the sender's user info, another
    -- row joining that conversation to the recipient's user info.
    (
    -- join conversations and users based on sender
    SELECT
      conversations.*, users.id AS user_id, users.username AS other_user
    FROM
      conversations
    INNER JOIN
      users ON users.id = conversations.sender_id
    UNION
    -- join conversations and users based on recipient
    SELECT
      conversations.*, users.id AS user_id, users.username AS other_user
    FROM
      conversations
    INNER JOIN
      users ON users.id = conversations.recipient_id
    ) AS convos_involving_user
  -- Now that we conceptually have that big join table with two rows for
  -- each conversation, we filter that table. First, we are only interested
  -- in the conversations where either the recipient or sender is the
  -- current user. But we still have duplicate rows for each message, so we
  -- also filter out the rows that join a conversation rows to the
  -- current_user's row. This leaves, for each conversation involving the
  -- current user, the row that links the conversation to the other user.
  WHERE
    (recipient_id = ? OR sender_id = ?) AND user_id != ?
SQL

然后每个conversations都会有一个other_user方法,您可以在其上调用以获取其他用户的用户名。您可以在视图中使用它或诸如此类的东西。使用other_user方法进行说明:

conversations.each { |convo| puts convo.other_user }

希望这有帮助。