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
相关产品推荐
相关产品推荐

