我有一个在两个用户之间运行的简单消息系统。
创建conversation
的用户获得一条记录,我可以通过User.find(sender_id).conversation.last
访问该记录,但是,如果我尝试访问User.find(recipient_id).conversation.last
,则接收者得到一个=> nil(我用{ofc替换了receive_id和sender_id实际ID)。
但是,两个用户都可以获取与对话关联的消息并可以聊天。我根据Dana Mulder on Medium的教程使用外键。我认为这很奇怪,因为我希望两个用户(接收者和发送者)都应该能够访问他们所参与的对话的记录。有办法实现吗?
我的模特:
User.rb
has_many :conversations, :foreign_key => :sender_id, dependent: :destroy
has_many :messages, through: :conversations
Conversation.rb
belongs_to :sender, :foreign_key => :sender_id, class_name: 'User'
belongs_to :recipient, :foreign_key => :recipient_id, class_name: 'User'
has_many :messages, dependent: :destroy
Message.rb
belongs_to :conversation
belongs_to :user
对话控制器:
conversations_controller.rb
def create
if Conversation.between(params[:sender_id],params[:recipient_id]).present?
@conversation = Conversation.between(params[:sender_id], params[:recipient_id]).first
else
@conversation = Conversation.create!(conversation_params)
end
redirect_to conversation_messages_path(@conversation)
end
您是否知道如何使两个用户都可以进行对话? (它可以访问,但不是我需要的方式)。
提前谢谢!
答案 0 :(得分:2)
您与会话的用户关联仅在寻找sender_id
has_many :conversations, :foreign_key => :sender_id, dependent: :destroy
收件人用户正在寻找其ID为sender_id
而不是recipient_id
的会话。
我认为您可以通过在用户和对话之间添加联接模型(而不是仅属于发件人和收件人的对话)来解决此问题(尽管您仍然应该保存这些引用)。
类似
class ConversationsUsers < ....
belongs_to :user
belongs_to :conversation
end
class User < ...
has_many :conversations_users
has_many :conversations, through: :conversations_users
has_many :started_conversations, class_name: 'Conversation', foreign_key: :sender_id
has_many :received_conversations, class_name: 'Conversation', foreign_key: :recipient_id
end
class Conversation < ...
has_many :convesations_users
end
对于每个“对话”,在sessions_users表上都有两个记录,每个用户一个。现在,两个用户都可以查询所有对话,而不必考虑是发件人还是收件人(如果您打算扩展对话,您也可以有任意数量的参与者参与对话!)。
尽管您必须手动创建一些记录,但是在创建“对话”之后,您可以使用after回调为每个用户创建两个对话用户对象。
另一种选择是只使用一种方法
def conversations
Conversation.where(sender_id: id).or(Conversation.where(recipient_id: id))
end
但是您将无法使用joins / includes / etc。
编辑:要获取所有消息,请添加另一种方法:
def messages
conv_ids = conversations.pluck(:id)
Message.where(conversation_id: conv_ids)
end
然后您就可以获取所有已阅读的邮件
current_user.messages.where(read: true)