ruby-on-rails - Rails 渲染 JSON 导致辅助方法被调用两次
问题描述
当我从 Rails 应用程序渲染 JSON 时,我遇到了奇怪的行为。一个辅助方法在render :json
被调用时会运行两次。这是控制器和方法:
class UsersController < ApplicationController
def current
render json: { :errors => "Incorrect credentials" }, :status => :bad_request
end
end
我有以下帮助模块,带有puts
调试语句:
module SessionsHelper
def current_user
puts "current_user"
if encrypted_id = request.headers[:user_id]
user = User.find_by(id: EncryptionService.decrypt(encrypted_id))
if user && user.authenticated?(request.headers[:remember_token])
@curent_user = user
end
end
end
end
SessionsHelper 包含在应用程序控制器中
class ApplicationController < ActionController::API
include SessionsHelper
end
发送请求后,我得到以下信息:
Started GET "/user/current" for ::1 at 2021-02-12 22:06:47 -0800
Processing by UsersController#current as */*
Parameters: {"user"=>{}}
current_user
[active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (0.06ms)
Completed 400 Bad Request in 1ms (Views: 0.7ms | ActiveRecord: 6.6ms | Allocations: 383)
current_user
被打印了,即使该函数从未被调用过。当我注释掉render json:
声明时,离开:
class UsersController < ApplicationController
def current
end
end
我得到以下信息:
Started GET "/user/current" for ::1 at 2021-02-12 22:09:43 -0800
Processing by UsersController#current as */*
Parameters: {"user"=>{}}
Completed 204 No Content in 0ms (ActiveRecord: 4.2ms | Allocations: 78)
current_user
不打印。为什么会render json:
打电话current_user
?在我的实际应用程序中,这会导致数据库被命中两次(尽管 Rails 明智地缓存了结果)。
更新:我在这里做点什么。我跑去puts caller[0]
看看是谁在调用这个函数。结果:
/Users/izaguirrejoe/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/active_model_serializers-0.10.12/lib/action_controller/serialization.rb:40:in 'serialization_scope'
def serialization_scope
return unless _serialization_scope && respond_to?(_serialization_scope, true)
send(_serialization_scope)
end
有任何想法吗?
解决方案
我看到您正在使用 active_model_serializers,如果您查看他们在此处所说的文档,则默认序列化范围是:current_user
. 它还强调,
重要提示:由于范围是在渲染时设置的,您可能需要对其进行自定义,以便不会在每个请求上调用 current_user。这也是 0.9 中的一个问题。
这导致该current_user
方法总是被调用。如果你想避免这种行为,你可以serialization_scope
在控制器中设置例如:
class UsersController < ApplicationController
serialization_scope nil # also you can pass a custom method here
def current
render json: { :errors => "Incorrect credentials" }, :status => :bad_request
end
end
或者在某些情况下仅通过调用self.class.serialization_scope nil
.
推荐阅读
- android - 针对 API 版本 18+ 的 Android KeyPairGenerator RSA 加密时间优化
- reactjs - 为什么我无法使用 Next.js 的 getInitialProps 获取我的 Metamask 帐户地址?
- php - 如何在codeigniter 3中打印api响应
- java - com.applitools.eyes.ServerConnector.startSession(ServerConnector.java:166)
- c# - 当数据来自 while 循环函数并显示在列表视图中时,如何将数据存储在 SQL Server 表中?
- python - 使用表单参数将 CURL 命令转换为 POST Python 请求
- azure - 更改 cosmosDB 吞吐量的 Powershell 脚本出现 401 错误
- excel - 使用 Excel 公式的每个条件的最小日期
- java - 使用gson在java中读取json对象文件保持为空
- python - 找出 25 和 50 派萨硬币的所有可能组合,加起来换算成 5 卢比