一个用户的关联记录为零,而另一用户则为零

时间:2018-09-19 00:06:05

标签: ruby-on-rails activerecord associations

我有一个在两个用户之间运行的简单消息系统。 创建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

您是否知道如何使两个用户都可以进行对话? (它可以访问,但不是我需要的方式)。

提前谢谢!

1 个答案:

答案 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)