Rails中如何将Template模型参数传递给Prawn生成的PDF视图
实现方案
1. 改造Prawn PDF类支持参数传入
首先修改ReportPdf的初始化方法,支持接收动态参数,为了兼容多类型PDF的通用需求,直接用哈希传参即可:
class ReportPdf < Prawn::Document # 新增参数接收,args为哈希,可传入任意你需要的动态数据 def initialize(args = {}) # 调用父类构造方法,也可以在这里传pdf全局配置,比如页面大小、边距等 super() # 把传入的参数存为实例变量,所有实例方法都可以调用 @template = args[:template] @templates = args[:templates] header text_content end def header image "#{Rails.root}/app/assets/images/logo.jpg", width: 230, height: 75 end def text_content y_position = cursor - 50 bounding_box([0, y_position], :width => 270, :height => 300) do # 替换成动态内容即可 text "表单信息", size: 15, style: :bold text "This form is for #{@template.name} who lives at #{@template.address} and has an id of #{@template.NationalId}" text "Lorem ipsum dolor sit amet, consectetur adipiscing elit. ." end bounding_box([300, y_position], :width => 270, :height => 300) do text "Duis vel", size: 15, style: :bold text "Duis vel tortor elementum, ultrices tortor vel, accumsan dui. Nullam in dolor rutrum, gravida turpis eu, vestibulum lectus. Pellentesque aliquet dignissim justo ut fringilla. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut venenatis massa non eros venenatis aliquet. Suspendisse potenti. Mauris sed tincidunt mauris, et vulputate risus. Aliquam eget nibh at erat dignissim aliquam non et risus. Fusce mattis neque id diam pulvinar, fermentum luctus enim porttitor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos." end end end
2. 控制器层传递数据
根据你生成PDF的场景,在对应控制器动作里把模型数据传入PDF类即可:
单条Template详情PDF(对应show页面)
给show动作新增pdf响应逻辑:
def show respond_to do |format| format.html format.pdf do # 把查询到的@template传入PDF类 pdf = ReportPdf.new(template: @template) send_data pdf.render, filename: "template_#{@template.id}.pdf", type: 'application/pdf', disposition: "inline" end end end
多条Template列表PDF(对应index页面)
如果要生成所有模板的汇总PDF,直接传入集合即可:
def index @templates = Template.all respond_to do |format| format.html format.pdf do pdf = ReportPdf.new(templates: @templates) send_data pdf.render, filename: 'templates_report.pdf', type: 'application/pdf', disposition: "inline" end end end
3. 多类型PDF通用适配方案
要支持报告、证书等不同类型的PDF,你可以抽一个公共PDF基类,把通用逻辑(比如页眉、页脚、字体配置)放在基类里,不同类型的PDF继承基类实现各自的内容逻辑即可:
# app/pdfs/base_pdf.rb class BasePdf < Prawn::Document def initialize(args = {}) # 统一配置页面大小、边距、字体等 super(page_size: 'A4', margin: 30) set_font header content footer end def set_font # 统一配置字体,支持中文的话可以在这里加载自定义字体 end def header # 通用页眉逻辑,比如Logo、站点名称 end def footer # 通用页脚逻辑,比如页码、版权信息 end def content # 子类各自实现 raise NotImplementedError, "子类需要实现content方法" end end # 报告类PDF class ReportPdf < BasePdf def initialize(args = {}) @templates = args[:templates] super end def content # 报告专属内容逻辑 end end # 证书类PDF class CertificatePdf < BasePdf def initialize(args = {}) @user = args[:user] @course = args[:course] super end def content # 证书专属内容逻辑 end end
额外修正
你的表单代码里重复写了两次address字段,把第二个address字段替换为name字段,否则提交表单时无法获取name参数:
<div class="field"> <%= form.label :name %> <%= form.text_field :name %> </div> <div class="field"> <%= form.label :address %> <%= form.text_field :address %> </div> <div class="field"> <%= form.label :NationalId %> <%= form.text_field :NationalId %> </div>
内容的提问来源于stack exchange,提问作者dragoon
相关产品推荐
相关产品推荐

