假设我们有 rails API 。在许多控制器方法中,我需要设置我的current_object,这要归功于请求中的params。然后我可以设置 before_action ,如:
def set_current_object
if My_object.exists? params[:id]
@current_object = My_object.find params[:id]
else
render json: {error: 'Object not found'}.to_json, status:404
end
end
这没关系。但我想在我的控制器方法中动态设置current_object 。想象一下,我在一个控制器中有一个show方法,我需要使用我的current_object:
def show
render json: {object_name: current_object.name}.to_json, status: 200
end
current_object将是一个辅助方法,如:
def current_object
if My_object.exists? params[:id]
return My_object.find params[:id]
else
render json: {error: 'Object not found'}.to_json, status:404
end
end
然后,如果My_object.exists? params [:id]为false我想发送404并停止我的控制器方法。就像这里写的一样,它显然不起作用。有什么建议吗?
答案 0 :(得分:2)
你走在正确的轨道上。通常你会实现这种"延迟加载"作为memoizes使用||=
idiom返回值的方法。
您只需修改current_object
帮助程序,以便在无法返回有效值时触发404错误。通常,您可以通过引发可识别的异常(例如ActiveRecord::RecordNotFound
)并使用rescue_from
子句在控制器中处理此异常来执行此操作。
class ApplicationController
def current_object
if My_object.exists? params[:id]
# memozie the value so subsequent calls don't hit the database
@current_object ||= My_object.find params[:id]
else
raise ActiveRecord::RecordNotFound
end
end
rescue_from ActiveRecord::RecordNotFound with: :show_404
def show_404
render json: {error: 'Object not found'}.to_json, status:404
end
end
现在,因为您在控制器层次结构的顶层遵循处理ActiveRecord::RecordNotFound
的非常标准的Rails约定,所以现在可以大大清理current_object
方法。而不是检查是否存在记录,只是尝试按ID查找记录。如果它不存在,ActiveRecord将自动为您引发异常。实际上,您的整个current_object
方法应该是一行代码:
class ApplicationController
def current_object
@current_object ||= My_object.find(params[:id])
end
rescue_from ActiveRecord::RecordNotFound with: :show_404
def show_404
render json: {error: 'Object not found'}.to_json, status:404
end
end
答案 1 :(得分:0)
假设My_object
是一个模型,如果您只使用find
,那么数据库中不存在的params[:id]
将引发ActiveRecord::RecordNotFound
错误,和Rails' ActionController::Base
将捕获异常并默认呈现404:
def current_object
My_object.find params[:id]
end