【问题标题】:associated record is nil for one user but not for the other一个用户的关联记录为零,但另一用户的关联记录为零
【发布时间】:2018-09-19 00:06:05
【问题描述】:

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

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

我的模型:

用户.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

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

提前致谢!

【问题讨论】:

    标签: ruby-on-rails activerecord associations


    【解决方案1】:

    您与对话的用户关联只是寻找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
    

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

    不过,您必须手动创建一些记录,在创建对话后,您可以使用 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)
    

    【讨论】:

    • 再次感谢您的回复。我想让它尽可能轻巧,因为我已经有了很多模型和东西。我很快就会尝试选项 2。
    • 该方法部分完成了工作。我现在可以通过所涉及的每个用户访问对话,但不幸的是,这仅适用于对话,不适用于相关消息。我需要Conversation.where(sender_id: id).or(Conversation.where(recipient_id: id)).messages.where(read: true)
    • 您可以通过 2 个步骤(2 个查询)来完成:conv_ids = conversations.pluck(:id); Message.where(conversation_id: conv_ids, read: true)
    • 我应该把conv_ids = conversations.pluck(:id);放在哪里?在conversations 方法下会给我一个错误undefined local variable or method conversations' for User`
    • 检查我的编辑,应该是另一种方法,因为 conversations 还没有定义
    猜你喜欢
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多