Rails自定义Patch路由status动作触发ActiveRecord::RecordNotFound报错
解决Rails嵌套路由中自定义Patch动作的ActiveRecord::RecordNotFound问题
看起来你遇到的问题核心是shallow嵌套路由下自定义动作的参数匹配和资源查找逻辑不兼容,我来帮你一步步排查解决:
1. 先确认路由生成结果
首先在终端运行命令,查看自定义动作的路由详情:
rails routes | grep status
你应该会看到类似这样的路由结构:
status_gig PATCH /gigs/:id/status(.:format) gigs#status
重点确认路由参数是:id,而非:gig_id或需要额外的project_id。
2. 检查控制器的before_action回调
默认update动作能正常运行,说明你的set_gig(用于查找Gig资源的回调方法)逻辑是正确的,但大概率你没把status动作加入到回调的生效列表中。比如之前的代码可能是:
before_action :set_gig, only: [:show, :edit, :update, :destroy]
把它修改为包含status动作:
before_action :set_gig, only: [:show, :edit, :update, :destroy, :status]
3. 确保set_gig方法兼容shallow路由
因为shallow模式下,自定义动作的路由是直接/gigs/:id/status,不会携带project_id参数,所以你的set_gig方法需要同时支持**嵌套路径(带project_id)和浅路径(不带project_id)**两种场景:
def set_gig if params[:project_id].present? @project = Project.find(params[:project_id]) @gig = @project.gigs.find(params[:id]) else @gig = Gig.find(params[:id]) end end
这样无论请求来自嵌套路径还是浅路径,都能正确定位到对应的Gig资源。
4. 排查动作内的手动查找逻辑
如果你没有依赖set_gig回调,而是在status动作里手动查找Gig,一定要确保使用正确的参数名:
def status # 正确写法:使用路由传递的:id参数 @gig = Gig.find(params[:id]) # ... 你的属性更新逻辑 end
别误写成params[:gig_id]或其他参数名,这会直接导致查找失败。
做完这些调整后,再测试/gigs/2/status的Patch请求,应该就能正常找到Gig并更新属性了。
内容的提问来源于stack exchange,提问作者chrisgeeq
相关产品推荐
相关产品推荐

