2013-11-13 7 views
0

У меня есть модель User и Message одна с sender_id и recipient_id.Последний контакт с пользователем

Я хотел бы получить все пользователей Я связался или с вами связались.

Я пробовал:

has_many :message_received_by_user, class_name: 'Message', foreign_key: :recipient_id, select: "DISTINCT ON (messages.sender_id) messages.sender_id, messages.created_at, messages.body" , order: "messages.sender_id, messages.created_at DESC" 

Но это только дает мне одну сторону (те, кто связался со мной).

Как я могу использовать обе стороны?

Большое спасибо

+0

имеет много отношение должно быть во множественном числе (message_received_by_users) и принадлежит единственному. –

+0

Означает ли это, что я не могу добиться того, что я хотел бы сделать, используя 'has_many'? – titibouboul

ответ

2

Ниже этого раздела мой первоначальный ответ; Я неправильно прочитал вопрос и подумал, что OP хотел только список пользователей, которые ПОЛУЧИЛИ сообщения от указанного пользователя; Я также не заметил, что касается также пользователей, которые отправили SENT-сообщения указанному пользователю. Вот мое обновление. Я оставлю исходный ответ ниже, если это поможет.

В этой версии ответа, я изменил бы присоединиться и где положение так, что запрос рассматривается либо sender_id или recipient_id колонки:

User.joins("INNER JOIN messages ON (messages.sender_id = users.id OR messages.recipient_id = users.id)") 
    .where("messages.sender_id = ? OR messages.recipient_id = ?", current_user.id, current_user.id).uniq 

Извинения за недоразумение.


ОРИГИНАЛЬНЫЙ ОТВЕТ:

Для того, чтобы получить все пользователи, вы связывались, я имею в виду, самый простой подход должен сделать это с помощью обычных активных методов записи запроса. Во-первых, настроить has_many в вашей User модели следующим образом:

В вашей User модели

has_many :messages_sent, class_name: "Message", foreign_key: :sender_id 
has_many :messages_received, class_name: "Message", foreign_key: :recipient_id 

И потом, вы можете просто запрос с использованием отношения как так:

User.joins(:messages_received).where(:messages=>{sender_id: current_user.id}).uniq 

Примечание: замените current_user тем, что вы используете для хранения целевого пользователя.

Редактировать

Кто-то спросил, почему это лучше, чем при использовании прямого :messages_sent отношения. Преимущество такого подхода заключается в том, что все это делается на уровне базы данных, где правильное индексирование может выполнять свою работу. Если у вас очень большая таблица, и этот пользователь отправил большое количество сообщений, использование активной записи has_many будет требовать, чтобы вы перебирали большую коллекцию, пытаясь найти уникальных пользователей.

Просто, чтобы добавить немного больше разъяснений, этот запрос должен отображать запрос SQL, который выглядит примерно так:

SELECT users.* 
FROM users INNER JOIN messages ON messages.recipient_id = users.id 
WHERE messages.sender_id = 1 

В простом английском языке, это в основном говорят, к базе данных: «Пожалуйста, дайте мне все пользователи, которые ПОЛУЧИЛИ сообщение SENT пользователем # 1 ".

+0

Да, это был я! Я удалил комментарий, потому что я не правильно прочитал вопрос! В вашем ответе по-прежнему отсутствует способ получить пользователей, которые отправили или получили сообщения целевому пользователю, но я не уверен, что это возможно в одном запросе без написания SQL – Slicedpan

+0

@Slicedpan Нет проблем, это был справедливый вопрос. Хм, я не совсем уверен, что вы имеете в виду (повтор: вторая часть вашего комментария). Способы поиска активной записи вызывают в модели User. В конечном итоге это вызовет запрос, который выглядит так: 'SELECT users. * FROM users INNER JOIN messages ON messages.recipient_id = users.id WHERE messages.sender_id = 1'. Как вы можете видеть (если я действительно что-то не хватает), вы действительно получите список пользователей, которые получили сообщения от целевого пользователя. –

+2

Я думаю, что вам нужен запрос 'SELECT. * FROM users INNER JOIN messages AS r_msg ON r_msg.recipient_id = users.id INNER JOIN messages AS s_msg ON s_msg.sender_id = users.id WHERE s_msg.recipient_id = 1 ИЛИ r_msg. recipient_id = 1; 'т.е. все пользователи, которые получили сообщение от пользователя 1 или отправили сообщение пользователю 1 – Slicedpan

0

Вы можете сделать так:

перенастройки будет выглядеть следующим образом:

class CreateMessages < ActiveRecord::Migration 
    create_table :messages do |t| 
    def up 
     t.references :sender 
     t.references :recipient 
     t.string :message 
    end 
    end 
end 

Вы модель: -

class Message < ActiveRecord::Base 
    belongs_to :sender, class_name => 'User' 
    belongs_to :recipient, class_name => 'User' 
end 

И эти другие являются ассоциации с другой стороны (модель пользователя):

class User < ActiveRecord::Base 
has_many :sent_messages, :class_name => 'Message', :foreign_key => 'sender_id' 
has_many :received_messages, :class_name => 'Message', :foreign_key => 'recipient_id' 
end 

Это позволит вам получить все, отправленных или полученных пользователя сообщений, как это:

@user.sent_messages 
@user.received_messages 

Благодаря

+0

Мне нравятся разные пользователи, а не сообщения! – titibouboul

0

см railscast http://railscasts.com/episodes/163-self-referential-association или How to Implement a Friendship Model in Rails 3 for a Social Networking Application?

я реализовать его в Mongoid как

модели пользователя

has_many :friendships, inverse_of: :owner 

def friends 
    #retrive all the friendships and collect users have sent me a request or being sent a request. 
    fs = Friendship.any_of({:friend_id.in => [self.id]}, {:owner_id.in => [self.id]}).where(state: 'accepted') 
    User.in(id: fs.collect{|i| [i.friend_id, i.owner_id]}.flatten - [self.id]) 
end 

модель Дружба

belongs_to :owner, class_name: 'User' #user who sent friend request is the owner 
belongs_to :friend, class_name: "User" #user to whom request is sent. 
Смежные вопросы