我是json的新手并且遇到了返回问题。我收到了下面的错误,即使我在render
,我也return
。是什么导致了这个错误?
Abstract Atroller :: Api中的DoubleRenderError :: V1 :: ArticlesController#show
在此操作中多次调用渲染和/或重定向。
错误是指render json: {errors: "not authorized" }, status: :unauthorized
下面的def authenticate_user
。相反,我希望它只是呈现一个json错误:"未授权"。知道为什么没有发生这种情况吗?
before_action :authenticate
def authenticate
unless authenticated?
render json: {errors: "not authorized" }, status: :unauthorized
return
end
end
这将调用以下辅助方法:
def authenticated?
!current_user.nil?
end
def current_user
token = request.headers["Authorization"]
email = request.headers["HTTP_USER_EMAIL"]
if token
user = User.friendly.find_by(email: email)
if user
if user.token_expired?
render json: {errors: "Session expired, please login" }, status: :unauthorized
return
elsif user.authenticated?(token)
@current_user = user
end
end
else
nil
end
end
更新:提供的解决方案可以删除return
无处不在的工作,但我不明白为什么。假设辅助方法如下所示。那么包含return
是非常重要的,对吧?因为否则如果找不到@node,该方法仍将继续,并且找不到消息"节点"不会显示。你能解释一下吗?
def create
@node = Node.find_by(id: params[:node_id])
if @node.nil?
render json: { errors: "node not found" }, status: :bad_request
return
end
nodee = @node.create(create_params)
if nodee.save
render json: @node, status: :created
else
render json: @node, status: :bad_request
end
end
换句话说,我原本希望从render
删除def authenticate
会导致Rails继续使用create
方法,因为def authenticate
没有告诉它去那里(这就是我看到的render
)。
更新2:我也无法按照答案中的建议删除render
,而是将其移至该行的开头:return render json: {errors: "not authorized" }, status: :unauthorized
。很想明白为什么会这样。
答案 0 :(得分:1)
你的核心问题是current_user
正在进行渲染本身 - 这很不寻常,因此很容易意外渲染两次。第二件事是,如果在过滤器期间调用渲染或重定向,则前过滤器会停止对动作的处理:从过滤器返回并不会直接影响事物。
从current_user
中删除返回很大程度上是偶然的:这意味着current_user
的返回值是render的返回值,即不再为nil。这意味着authenticated?
返回true(即使用户未经过身份验证),因此您之前的过滤器不会再次呈现。然后Rails停止执行该操作,因为从过滤器中调用了渲染,因此看起来事情已经起作用。
一般情况下,你确实需要调用return来停止执行方法的其余部分,但是这显然不会在调用方法中停止进程。
就个人而言,我会按原样保留身份验证,但更改current_user,以便它不会产生任何副作用(除了设置@current_user)。如果你真的想要更改错误消息,那么在一个单独的实例变量中跟踪current_user为零的原因(事实上我可能不会滚动我自己的身份验证,但那是另一个故事)
答案 1 :(得分:0)
对于未来的旅行者:
在 Rails API 控制器中使用保护子句和辅助方法以避免多行 if else 链时,请执行以下操作:
干杯
def controller_method
return if invalid_email?(params["user"]["email"])
...
def invalid_email?(email)
if EmailValidator.invalid?(email) then render(json: { status: 422, message: "Your email format is invalid. Please check that your email is correct and try again!" }, status: 422) and return true end
end