类型错误 - 无法引用 Rack::Session::SessionId

Oat*_*ats 4 model-view-controller rack ruby-on-rails typeerror internal-server-error

我在尝试访问 Questions#Show 时遇到了一个神秘的错误。每当我重定向到视图时,我都会收到 500 内部服务器错误。根据我的服务器跟踪,问题出在“set_question”中的问题控制器中

\n\n
Started GET "/questions/1" for 127.0.0.1 at 2020-02-01 18:57:34 +0100\nProcessing by QuestionsController#show as HTML\n  Parameters: {"id"=>"1"}\n  User Load (1.1ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1\n  Question Load (3.5ms)  SELECT `questions`.* FROM `questions` WHERE `questions`.`id` = 1 LIMIT 1\n  \xe2\x86\xb3 app/controllers/questions_controller.rb:105:in `set_question\'\nCompleted 500 Internal Server Error in 15ms (ActiveRecord: 4.6ms | Allocations: 3861)\n\nTypeError - can\'t quote Rack::Session::SessionId:\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是我不太确定它出了什么问题

\n\n

问题控制器

\n\n
class QuestionsController < ApplicationController\n  before_action :set_question, only: [:show, :edit, :update, :destroy]\n  impressionist :actions => [:show], unique: [:session_hash]\n\n  def index\n  end\n\n  def show\n    @answers = @question.answers.includes(:user).page(params[:page]).per(5)\n  end\n\n  def new\n    @question = Question.new\n  end\n\n  def edit\n    authorize @question\n  end\n\n  def create\n    @question = Question.new(question_params)\n\n    respond_to do |format|\n      if @question.save\n        format.html { redirect_to @question, notice: \'You have successfully asked a question!\' }\n        format.json { render :show, status: :created, location: @question }\n      else\n        format.html { render :new }\n        format.json { render json: @question.errors, status: :unprocessable_entity }\n      end\n    end\n  end\n\n  def update\n    authorize @question\n    respond_to do |format|\n      if @question.update(question_params)\n        format.html { redirect_to @question, notice: \'Question successfully updated.\' }\n        format.json { render :show, status: :ok, location: @question }\n      else\n        format.html { render :edit }\n        format.json { render json: @question.errors, status: :unprocessable_entity }\n      end\n    end\n  end\n\n  def destroy\n    authorize @question\n    @question.destroy\n    respond_to do |format|\n      format.html { redirect_to @questions_url, notice: \'Question successfully deleted.\' }\n      format.json { head :no_content }\n    end\n  end\n\n  private\n\n  def set_question\n    @question = Question.find(params[:id])\n  end\n\n  def question_params\n    params.require(:question).permit(:title, :body, :tag_list).merge(user_id: current_user.id)\n  end\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

有人熟悉这个类型错误吗?我已经尝试过 Google 和 StackOverflow,但没有看到任何提示\n我对其他模型使用了几乎相同的代码,但这是唯一一个给我带来 TypeError 的代码

\n\n

堆栈跟踪

\n\n
activerecord (6.0.2.1) lib/active_record/connection_adapters/abstract/quoting.rb:231:in `_quote\'\nactiverecord (6.0.2.1) lib/active_record/connection_adapters/abstract/quoting.rb:18:in `quote\'\nactiverecord (6.0.2.1) lib/arel/collectors/substitute_binds.rb:17:in `add_bind\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:703:in `visit_Arel_Nodes_BindParam\'\nactiverecord (6.0.2.1) lib/arel/visitors/visitor.rb:31:in `visit\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:611:in `visit_Arel_Nodes_Equality\'\nactiverecord (6.0.2.1) lib/arel/visitors/visitor.rb:31:in `visit\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:790:in `block in inject_join\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:788:in `each\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:788:in `each_with_index\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:788:in `inject_join\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:578:in `visit_Arel_Nodes_And\'\nactiverecord (6.0.2.1) lib/arel/visitors/visitor.rb:31:in `visit\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:790:in `block in inject_join\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:788:in `each\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:788:in `each_with_index\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:788:in `inject_join\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:181:in `collect_nodes_for\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:161:in `visit_Arel_Nodes_SelectCore\'\nactiverecord (6.0.2.1) lib/arel/visitors/mysql.rb:28:in `visit_Arel_Nodes_SelectCore\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:128:in `block in visit_Arel_Nodes_SelectStatement\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:127:in `each\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:127:in `inject\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:127:in `visit_Arel_Nodes_SelectStatement\'\nactiverecord (6.0.2.1) lib/arel/visitors/mysql.rb:23:in `visit_Arel_Nodes_SelectStatement\'\nactiverecord (6.0.2.1) lib/arel/visitors/visitor.rb:31:in `visit\'\nactiverecord (6.0.2.1) lib/arel/visitors/visitor.rb:11:in `accept\'\nactiverecord (6.0.2.1) lib/arel/visitors/to_sql.rb:18:in `compile\'\nactiverecord (6.0.2.1) lib/active_record/connection_adapters/abstract/database_statements.rb:34:in `to_sql_and_binds\'\nactiverecord (6.0.2.1) lib/active_record/connection_adapters/abstract/query_cache.rb:99:in `select_all\'\nactiverecord (6.0.2.1) lib/active_record/connection_adapters/mysql/database_statements.rb:12:in `select_all\'\nactiverecord (6.0.2.1) lib/active_record/connection_adapters/abstract/database_statements.rb:77:in `select_one\'\nactiverecord (6.0.2.1) lib/active_record/relation/finder_methods.rb:317:in `block in exists?\'\nactiverecord (6.0.2.1) lib/active_record/relation.rb:828:in `skip_query_cache_if_necessary\'\nactiverecord (6.0.2.1) lib/active_record/relation/finder_methods.rb:317:in `exists?\'\nimpressionist (1.6.1) app/controllers/impressionist_controller.rb:103:in `check_unique_impression?\'\nimpressionist (1.6.1) app/controllers/impressionist_controller.rb:99:in `check_impression?\'\nimpressionist (1.6.1) app/controllers/impressionist_controller.rb:94:in `unique?\'\nimpressionist (1.6.1) app/controllers/impressionist_controller.rb:44:in `impressionist_subapp_filter\'\nimpressionist (1.6.1) app/controllers/impressionist_controller.rb:7:in `block in impressionist\'\nactivesupport (6.0.2.1) lib/active_support/callbacks.rb:429:in `instance_exec\'\nactivesupport (6.0.2.1) lib/active_support/callbacks.rb:429:in `block in make_lambda\'\nactivesupport (6.0.2.1) lib/active_support/callbacks.rb:201:in `block (2 levels) in halting\'\nactionpack (6.0.2.1) lib/abstract_controller/callbacks.rb:34:in `block (2 levels) in <module:Callbacks>\'\nactivesupport (6.0.2.1) lib/active_support/callbacks.rb:202:in `block in halting\'\nactivesupport (6.0.2.1) lib/active_support/callbacks.rb:514:in `block in invoke_before\'\nactivesupport (6.0.2.1) lib/active_support/callbacks.rb:514:in `each\'\nactivesupport (6.0.2.1) lib/active_support/callbacks.rb:514:in `invoke_before\'\nactivesupport (6.0.2.1) lib/active_support/callbacks.rb:110:in `block in run_callbacks\'\npublic_activity (1.6.4) lib/public_activity/utility/store_controller.rb:27:in `store_controller_for_public_activity\'\nactivesupport (6.0.2.1) lib/active_support/callbacks.rb:121:in `block in run_callbacks\'\nactivesupport (6.0.2.1) lib/active_support/callbacks.rb:139:in `run_callbacks\'\nactionpack (6.0.2.1) lib/abstract_controller/callbacks.rb:41:in `process_action\'\nactionpack (6.0.2.1) lib/action_controller/metal/rescue.rb:22:in `process_action\'\nactionpack (6.0.2.1) lib/action_controller/metal/instrumentation.rb:33:in `block in process_action\'\nactivesupport (6.0.2.1) lib/active_support/notifications.rb:180:in `block in instrument\'\nactivesupport (6.0.2.1) lib/active_support/notifications/instrumenter.rb:24:in `instrument\'\nactivesupport (6.0.2.1) lib/active_support/notifications.rb:180:in `instrument\'\nactionpack (6.0.2.1) lib/action_controller/metal/instrumentation.rb:32:in `process_action\'\nactionpack (6.0.2.1) lib/action_controller/metal/params_wrapper.rb:245:in `process_action\'\nactiverecord (6.0.2.1) lib/active_record/railties/controller_runtime.rb:27:in `process_action\'\nactionpack (6.0.2.1) lib/abstract_controller/base.rb:136:in `process\'\nactionview (6.0.2.1) lib/action_view/rendering.rb:39:in `process\'\nrack-mini-profiler (1.1.5) lib/mini_profiler/profiling_methods.rb:104:in `block in profile_method\'\nactionpack (6.0.2.1) lib/action_controller/metal.rb:191:in `dispatch\'\nactionpack (6.0.2.1) lib/action_controller/metal.rb:252:in `dispatch\'\nactionpack (6.0.2.1) lib/action_dispatch/routing/route_set.rb:51:in `dispatch\'\nactionpack (6.0.2.1) lib/action_dispatch/routing/route_set.rb:33:in `serve\'\nactionpack (6.0.2.1) lib/action_dispatch/journey/router.rb:49:in `block in serve\'\nactionpack (6.0.2.1) lib/action_dispatch/journey/router.rb:32:in `each\'\nactionpack (6.0.2.1) lib/action_dispatch/journey/router.rb:32:in `serve\'\nactionpack (6.0.2.1) lib/action_dispatch/routing/route_set.rb:837:in `call\'\nrack-pjax (1.1.0) lib/rack/pjax.rb:12:in `call\'\nbullet (6.1.0) lib/bullet/rack.rb:15:in `call\'\nremotipart (1.4.4) lib/remotipart/middleware.rb:32:in `call\'\nwarden (1.2.8) lib/warden/manager.rb:36:in `block in call\'\nwarden (1.2.8) lib/warden/manager.rb:34:in `catch\'\nwarden (1.2.8) lib/warden/manager.rb:34:in `call\'\nrack (2.1.2) lib/rack/tempfile_reaper.rb:17:in `call\'\nrack (2.1.2) lib/rack/etag.rb:27:in `call\'\nrack (2.1.2) lib/rack/conditional_get.rb:27:in `call\'\nrack (2.1.2) lib/rack/head.rb:14:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/http/content_security_policy.rb:18:in `call\'\nrack (2.1.2) lib/rack/session/abstract/id.rb:269:in `context\'\nrack (2.1.2) lib/rack/session/abstract/id.rb:263:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/cookies.rb:648:in `call\'\nactiverecord (6.0.2.1) lib/active_record/migration.rb:567:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call\'\nactivesupport (6.0.2.1) lib/active_support/callbacks.rb:101:in `run_callbacks\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/callbacks.rb:26:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/executor.rb:14:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/actionable_exceptions.rb:17:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:32:in `call\'\nweb-console (4.0.1) lib/web_console/middleware.rb:132:in `call_app\'\nweb-console (4.0.1) lib/web_console/middleware.rb:28:in `block in call\'\nweb-console (4.0.1) lib/web_console/middleware.rb:17:in `catch\'\nweb-console (4.0.1) lib/web_console/middleware.rb:17:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call\'\nrailties (6.0.2.1) lib/rails/rack/logger.rb:38:in `call_app\'\nrailties (6.0.2.1) lib/rails/rack/logger.rb:26:in `block in call\'\nactivesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `block in tagged\'\nactivesupport (6.0.2.1) lib/active_support/tagged_logging.rb:28:in `tagged\'\nactivesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `tagged\'\nrailties (6.0.2.1) lib/rails/rack/logger.rb:26:in `call\'\nsprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/remote_ip.rb:81:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/request_id.rb:27:in `call\'\nrack (2.1.2) lib/rack/method_override.rb:24:in `call\'\nrack (2.1.2) lib/rack/runtime.rb:24:in `call\'\nactivesupport (6.0.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/executor.rb:14:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/static.rb:126:in `call\'\nrack (2.1.2) lib/rack/sendfile.rb:113:in `call\'\nactionpack (6.0.2.1) lib/action_dispatch/middleware/host_authorization.rb:83:in `call\'\nrack-mini-profiler (1.1.5) lib/mini_profiler/profiler.rb:296:in `call\'\nwebpacker (4.2.2) lib/webpacker/dev_server_proxy.rb:23:in `perform_request\'\nrack-proxy (0.6.5) lib/rack/proxy.rb:57:in `call\'\nrailties (6.0.2.1) lib/rails/engine.rb:526:in `call\'\npuma (4.3.1) lib/puma/configuration.rb:228:in `call\'\npuma (4.3.1) lib/puma/server.rb:681:in `handle_request\'\npuma (4.3.1) lib/puma/server.rb:472:in `process_client\'\npuma (4.3.1) lib/puma/server.rb:328:in `block in run\'\npuma (4.3.1) lib/puma/thread_pool.rb:134:in `block in spawn_thread\' \n
Run Code Online (Sandbox Code Playgroud)\n

Ter*_*ara 7

我成功地重现了同样的异常。也许您的代码或您正在使用的 gem 正在使用session.id.

解决方案

如果您的代码用于session.id识别用户,则应在使用之前将其转换为字符串。

# Bad
user = User.find_by(session_id: session.id)
# => TypeError can't quote Rack::Session::SessionId

# Good
user = User.find_by(session_id: session.id.to_s)
# Success!
Run Code Online (Sandbox Code Playgroud)

如果您的代码不运行查询session.id,则您应该怀疑在机架会话中间插入处理的 gem。

调试步骤

这段代码运行在Rails 5.2.4.2.

# In controller
def new
  logger.info "class=#{session.id.class} to_s=#{session.id.to_s}"
end

# The log for the above code
# INFO -- class=Rack::Session::SessionId to_s=adf8...9af0 <- a long string
Run Code Online (Sandbox Code Playgroud)

如果您通过 运行查询session.id,您将得到TypeError.

SomethingModel.where(session_id: session.id).to_a
# => TypeError can't quote Rack::Session::SessionId
Run Code Online (Sandbox Code Playgroud)


小智 5

将以下代码替换为config/initializers/session_store.rb:

Rails.application.config.session_store :active_record_store, :key => '....'
Run Code Online (Sandbox Code Playgroud)

和

Rails.application.config.action_dispatch.session_store :active_record_store, :key => '....'
Run Code Online (Sandbox Code Playgroud)

为我修复了TypeError 无法引用 Rack::Session::SessionId问题。

注意:请确保将“...”替换为您自己的密钥。