【问题标题】:Why does my controller keep expecting to retrieve data even though I cleared out the database即使我清除了数据库,为什么我的控制器仍然期望检索数据
【发布时间】:2019-03-31 12:23:16
【问题描述】:

我正在制作一个 Rails 应用程序,使用 postgresql 作为数据库,您可以在其中与用户联系并从他们的帖子中向他们发送消息。我的种子文件创建了 10 个测试用户,我正在检查向其他用户发送消息的功能,但是没有用户可以进行测试,所以我跳上 rails 控制台并清除了会话和消息表,这样我就可以删除数据库中的所有关系但从那以后我一直收到这个错误:

    ActiveRecord::RecordNotFound in PagesController#index
    Couldn't find all Private::Conversations with 'id': (14, 2, 3, 5, 6, 8, 9, 
    10, 11, 1) (found 3 results, but was looking for 10).

这是我的 PagesController 索引操作中的代码:

def index
    @hobby_posts = Post.by_branch('hobby').limit(8)
    @study_posts = Post.by_branch('study').limit(8)
    @team_posts  = Post.by_branch('team').limit(8)
  end

为什么总是弹出这个错误?

我尝试完全删除数据库,重新创建数据库,重新运行迁移,但这似乎并没有清除对话

这是我的 ApplicationController 中的代码:

def opened_conversations_windows
    if user_signed_in?
      session[:private_conversations] ||= []
      @private_conversations_windows = Private::Conversation.includes(:recipient, :messages)
                                        .find(session[:private_conversations])
    else
      @private_conversations_windows = []
    end
  end

当我将 if 行更改为时,代码似乎“工作”

if (user_signed_in? && @private_conversations_windows)

但是当我这样做并与用户创建新聊天时,新聊天关系的创建会命中数据库,但聊天窗口不显示。 更新:

class Private::ConversationsController < ApplicationController

  def create
    recipient_id = Post.find(params[:post_id]).user.id
    @conversation = Private::Conversation.new(sender_id: current_user.id, 
                                             recipient_id: recipient_id)
    if @conversation.save
      Private::Message.create(user_id: current_user.id, 
                              conversation_id: @conversation.id, 
                              body: params[:message_body])

      add_to_conversations unless already_added?

      respond_to do |format|
        format.js {render partial: 'posts/show/contact_user/message_form/success'}
      end
    else
      respond_to do |format|
        format.js {render partial: 'posts/show/contact_user/message_form/fail'}
      end
    end
  end


  def close 
    @conversation_id = params[:id].to_i
    session[:private_conversations].delete(@conversation_id)
    respond_to do |format|
      format.js  
    end
  end

  private

  def add_to_conversations
    session[:private_conversations] ||= []
    session[:private_conversations] << @conversation.id
  end

  def already_added?
    session[:private_conversations].include?(@conversation.id)
  end

end

【问题讨论】:

    标签: ruby-on-rails ruby database postgresql postgresql-9.3


    【解决方案1】:

    session 变量在浏览器会话期间有效。所以这个错误意味着你在登录时删除了数据库记录,并且你没有适当地调整session[:private_conversations]

    您要么需要从session[:private_conversations] 中删除已删除的 id,要么调整您的查找以使其没有问题。

    我会把你的代码改成这样:

    def opened_conversations_windows
      if user_signed_in? && session[:private_conversations].present?
        @private_conversations_windows = Private::Conversation.includes(:recipient, :messages)
                                            .where(id: session[:private_conversations])
    
        # Update the session variable to only have the existing values
        session[:private_conversations] = @private_conversations_windows.map(&:id)
      else
        @private_conversations_windows = []
      end
    end
    

    请注意,我将find() 变成了where(id: )find 期望提供的所有 id 都存在。 where 不需要返回任何记录;它只是搜索,你得到你得到的。

    此外,我只在用户实际打开私人对话时才进行数据库查询。这很重要,因为如果您已登录但没有私人对话,它将运行错误的查询。 (WHERE id IS NULL 或类似的东西)

    最后,我让它对会话变量进行了一些清理,将其设置为仅存在于数据库中的变量。

    现在每当您设置 session[:private_conversations] 时(大概是当有人关闭/打开新对话时),您都可以将其设置为仅仍然存在的那些。

    您提到以下似乎有效:

    if (user_signed_in? && @private_conversations_windows)
    

    鉴于您发布的代码,我相信您实际上永远不会将@private_conversations_windows 设置为[] 以外的任何值。原因是,您当前正在尝试设置该变量,因此此时它应该为 nil。因为它总是 nil,所以你永远不会落入实际查询数据库的 if 一边。当然,它不会再出错了,但那是因为它不再做任何有用的事情了。它基本上相当于:

    def opened_conversations_windows
      @private_conversations_windows = []
    end
    

    【讨论】:

    • 是的,这似乎使它起作用,我将如何从session[:private_conversations]中删除已删除的ID
    • 谢谢它工作得很好。但就个人知识而言,您曾说过:您要么需要从 session[:private_conversations] 中删除已删除的 id,要么将您的发现调整为可以只找到一些。我将如何从会话中删除 id,因为我已经清除了数据库,但这似乎不起作用,那么我该怎么做呢?
    • 对。你一开始就没有发布设置session[:private_conversations] 的代码,所以我采取了没有找到一些没关系的路线。如果您发布该代码,我可能会想出其他东西,但我认为搜索松散一点是明智的 - 如果您能够找到 9/10 的对话,我想您不会不想完全 404 请求。
    • 我用 Private::Conversations 控制器的代码更新了我的问题
    • 我明白了。我以为您的控制器正在某处删除 Private::Conversation 记录。如果是这样,您可能希望在同一位置从 session[:private_conversations] 中删除 id。由于这不是真正应该发生的事情,您实际上有两个选择:1.)清除您的会话,使其不包含不存在的对话 2.)使控制器对一些不存在的对话没问题(比如我的上面的代码)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-31
    • 2016-05-23
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 2019-11-29
    相关资源
    最近更新 更多