You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby on Rails 7渲染.rtf.erb模板并导出RTF文件问题

无需第三方库实现Rails渲染RTF.erb模板并导出RTF文件

你当前的问题在于直接用File.read读取模板文件,只是获取了包含ERB标签的原始文本,没有触发ERB的渲染过程,导致输出内容里保留了<%= ... %>这类未解析的标签,自然会出现异常。以下是两种无需第三方库的正确实现方案:

方案一:使用Rails内置的render_to_string(推荐)

利用Rails原生的模板渲染机制,自动解析ERB标签并生成最终的RTF内容:

def show
  @order = Order.find(params[:id])
  raise NotFound unless @order
  if params[:format] == 'rtf'
    latest_order = Order.find_by(order_type: 'o', customer_id: @order.customer_id)
    if latest_order.nil?
      @client_addr = Customer.find(@order.customer_id).addresses[0]
      @shipping_addr = @client_addr
    else
      @client_addr = latest_order.client_address
      @shipping_addr = latest_order.shipping_address
    end

    # 渲染RTF.erb模板,生成处理后的内容
    rtf_content = render_to_string(
      template: 'orders/order', # 对应views/orders/order.rtf.erb,根据实际路径调整
      formats: [:rtf],
      layout: false # 禁用布局,避免混入HTML布局内容
    )

    # 发送RTF文件
    send_data rtf_content, 
              filename: "order_#{@order.id}.rtf",
              type: 'application/rtf',
              disposition: 'attachment' # 强制浏览器下载文件,可选
  else
    render
  end
end

关键说明:

  • render_to_string会触发Rails的模板渲染流程,自动解析ERB中的实例变量(如@client_addr),替换为实际值。
  • layout: false必须设置,否则会把应用的HTML布局混入RTF内容,导致文件损坏。
  • 模板路径需与实际文件位置匹配:如果模板在views/orders/order.rtf.erb,则template参数为'orders/order';如果在其他目录,比如views/shared/order.rtf.erb,则改为'shared/order'。

方案二:手动使用Ruby ERB库渲染

如果不想依赖Rails的渲染机制,可直接用Ruby内置的ERB库处理模板:

require 'erb'

def show
  @order = Order.find(params[:id])
  raise NotFound unless @order
  if params[:format] == 'rtf'
    latest_order = Order.find_by(order_type: 'o', customer_id: @order.customer_id)
    if latest_order.nil?
      @client_addr = Customer.find(@order.customer_id).addresses[0]
      @shipping_addr = @client_addr
    else
      @client_addr = latest_order.client_address
      @shipping_addr = latest_order.shipping_address
    end

    # 读取模板文件并初始化ERB实例
    template_path = Rails.root.join('app/views', 'orders', 'order.rtf.erb')
    template = ERB.new(File.read(template_path))
    # 绑定当前控制器上下文,让模板能访问实例变量
    rtf_content = template.result(binding)

    # 发送RTF文件
    send_data rtf_content, 
              filename: "order_#{@order.id}.rtf",
              type: 'application/rtf',
              disposition: 'attachment'
  else
    render
  end
end

额外注意事项:

  • 确保你的RTF模板语法合法:比如模板中的\rowd、\rgaph108等RTF控制符必须符合RTF规范,否则生成的文件可能无法被Word等软件正确打开。
  • 实例变量的空值处理:模板中<%= @client_addr.city rescue 'N/A'%>的写法可以保留,但建议在控制器中提前处理空值(比如判断@client_addr是否存在),减少模板中的逻辑。

内容的提问来源于stack exchange,提问作者Gulmuhammad Akbari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:23:17