首页 > 解决方案 > 一个用户的关联记录为零,但另一用户的关联记录为零

问题描述

我在两个用户之间运行了一个简单的消息传递系统。创建 a 的用户conversation获得我可以通过 访问的记录User.find(sender_id).conversation.last,但是如果我尝试访问,收件人将获得 => nil User.find(recipient_id).conversation.last(我用实际 ID 替换了收件人 ID 和发件人 ID)。

但是,两个用户都会收到与对话相关的消息并且可以聊天。我正在根据Medium 上的 Dana Mulder的教程使用外键。我认为这很奇怪,因为我希望两个用户(接收者和发送者)都应该能够访问他们正在进行的对话的记录。有没有办法做到这一点?

我的模型:

用户.rb

has_many :conversations, :foreign_key => :sender_id, dependent: :destroy
has_many :messages, through: :conversations

对话.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

消息.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

你知道如何让两个用户都能访问对话吗?(它是可访问的,但不是我需要的方式)。

提前致谢!

标签: ruby-on-railsactiverecordassociations

解决方案


您与对话的用户关联只是在寻找sender_id

has_many :conversations, :foreign_key => :sender_id, dependent: :destroy

接收用户正在寻找他的 id assender_id而不是 as的对话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

对于每个对话,您将在 conversations_users 表上有两条记录,每个用户都有一条记录。现在,两个用户都可以查询所有对话,无论是发件人还是收件人(如果您打算扩展对话,您也可以有任意数量的参与者!)。

但是,您必须手动创建一些记录,在创建 Conversation 之后,您可以有一个 after 回调来为每个用户创建两个 conversation_user 对象。


另一种选择是只使用一种方法

def conversations
  Conversation.where(sender_id: id).or(Conversation.where(recipient_id: id))
end

但您将无法使用连接/包含/等。

编辑:要获取所有消息,请添加另一种方法:

def messages
  conv_ids = conversations.pluck(:id)
  Message.where(conversation_id: conv_ids)
end

然后你可以这样来获取所有已读消息,例如

current_user.messages.where(read: true)

推荐阅读