Ruby on Rails双重渲染错误:Redirect与Return失效问题排查
解决AbstractController::DoubleRenderError问题
问题根源
generateWellLetter方法内的重复响应send_data属于Rails中的渲染操作(和render本质一致),你在调用send_data之后又执行了redirect_to,这已经在同一个请求里触发了两次响应操作,直接违反了“一个action只能执行一次render/redirect”的规则。而且你写的and return仅作用于format.html的内部代码块,无法终止整个generateWellLetter方法,所以redirect_to仍然会执行。update!方法的默认响应
Rails的update!(通常由ActiveAdmin或资源路由提供)在执行完你传入的代码块后,会自动触发默认响应逻辑(比如渲染模板或跳转)。也就是说,无论你在代码块内做了什么,update!最后都会额外执行一次响应,这就导致了第三次响应触发,最终抛出错误。
修复方案
第一步:修正generateWellLetter的逻辑
既然已经通过send_data返回了文件下载,就不需要再做跳转。浏览器在完成下载后会保留当前页面,若需要跳转可由前端处理,后端不能同时返回文件和跳转指令。修改后的方法:
def generateWellLetter(template, letterName, params) @URL = "#{ENV["API_HOST"]}/api/Document/Generate/#{template}" response = HTTParty.post(@URL, :body => params, :headers => { "Content-Type" => "application/json" }) Zip::InputStream.open(StringIO.new(response)) do |io| while entry = io.get_next_entry report = io.read send_data report, :filename => letterName + '.docx', :type => 'docx' return # 发送文件后直接终止方法 end end end
第二步:阻止update!的默认响应
在update!的代码块中,处理完自定义逻辑后必须明确终止后续的默认响应流程,避免重复响应:
def update template = resource.check_changes(params[:well_master]) paramString = resource.to_json update! do |format| if resource.errors.present? render :edit return # 终止update!后续逻辑 else if template != '' generateWellLetter(template, 'Rpt_Farm_Name', paramString) return # 执行下载后终止后续逻辑 else rec = resource.PERMIT format.html { redirect_to admin_well_master_path(rec) } return # 跳转后终止后续逻辑 end end end end
关键注意点
send_data、render、redirect_to都属于响应操作,一个请求中只能执行其中一种一次。and return仅作用于当前代码块,无法终止整个方法,要终止方法需单独使用return。- 资源类方法(如
update!)自带默认响应逻辑,手动处理响应后必须终止后续流程。
内容的提问来源于stack exchange,提问作者Sean Gillespie
相关产品推荐
相关产品推荐

