Розглянемо генерування PDF-файлів засобами Ruby on Rails на прикладі одного із моїх робочих проекті. Роботу будемо проводити за допомогою gem'а Prawn
Добавляємо в Gemfile нашого проекту наступні записи:
1 2 |
gem 'prawn', git: "https://github.com/prawnpdf/prawn.git", submodules: true gem 'prawn-table', git: "https://github.com/prawnpdf/prawn-table.git" |
та виконуємо bundle install
Включимо gem в автозагрузку (попередньо створивши файл) config/initializers/prawn.rb
1 |
require "prawn" |
При генеруванні pdf-файлу з кирилицею, для уникнення помилки:
Your document includes text that's not compatible with the Windows-1252 character set. If you need full UTF-8 support, use TTF fonts instead of PDF's built-in fonts .
необхідно підключити шрифт, наприклад verdatab.ttf
розпаковуємо архів в /public/fonts/verdana та підключаємо його(див далі)
Розглянемо простий приклад генерування pdf, на прикладі контроллера sklads_controller.rb, Якщо за адресою http://localhost:3000/admin/sklads. ми бачимо перелік товару на складу у вигляді веб-сторінки, то нижче наведений код, за посиланням http://localhost:3000/admin/sklads.pdf дасть pdf-файл, поки що із текстом "Hello"
1 2 3 4 5 6 7 8 9 10 |
respond_to do |format| format.html format.pdf do pdf = Prawn::Document.new pdf.text "Hello" send_data pdf.render, filename: "sklad_tovar.pdf", type: "application/pdf", disposition: "inline" end end |
disposition: "inline" дозволить відкрити pdf-файл у самому браузері, за змовчанням файл пропонується скачати, усі інші корисні опції prawn'а можна знайти на оф.сайті в розділі документації
У в'юсі лінк на pdf версію виглядатиме так
1 |
<%= link_to "PDF", admin_sklads_path(format: "pdf") %> |
Як ми бачимо все працює, і pdf-файл із гордим заголовком Hello успішно відкрився 🙂
Створимо директорію для класів генерування pdf-файлів
1 |
mkdir app/pdfs |
Для автопідгрузки класів із цієї директорії в config/application.rb добавим:
1 |
config.autoload_paths << "#{Rails.root}/app/pdfs" |
Створимо клас app/pdfs/order_pdf.rb який буде генерувати pdf-файли дня наших веб-сторінок, у мене він виглядає так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
class OrderPdf < Prawn::Document def initialize h super(top_margin: 20) font_families.update( "Verdana" => { :bold => Rails.root.join('public/fonts/verdana','verdanab.ttf'), :italic => Rails.root.join('public/fonts/verdana','verdanab.ttf'), :normal => Rails.root.join('public/fonts/verdana','verdanab.ttf') }) font "Verdana", size: 10 text h[:header], size: 28 text "Дата: #{DateTime.now().strftime('%d.%m.%Y %H:%M:%S')}\n\n" text h[:filter] data h[:data] end def data ar move_down 0 table ar do row(0).font_style = :bold columns(1..3).align = :right self.row_colors = ['FFFFFF','DDDDDD'] self.header = true end end end |
В контроллері:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
respond_to do |format| format.html do @sklads = @sklads.paginate(page: filtering_params[:page], per_page: filtering_params[:per_pages]) end format.pdf do data=[['#','Артикул','Модель','К-ть','Ціна','Вага','Сума','Вага всього']] start_num = 0 @sklads.each do |t| data << [start_num += 1, t.tovar_article, t.tovar_model, t.count, t.tovar_price, t.tovar_weight, t.sklad_summa, t.sklad_weight ] end data << [{:content =>"Всього",:colspan => 6},@sklad_summa_all,@sklad_weight_all] h={} h[:header]="Склад" filter_header="" if (filtering_params[:article].present?) filter_header += "Артикул: #{Tovar.find_by(id: filtering_params[:article]).article}\n" end if (filtering_params[:by_model].present?) filter_header += "Модель: #{Tovar.find_by(id: filtering_params[:article]).model}\n" end if (filtering_params[:search].present?) filter_header += "Пошук: #{filtering_params[:search]}\n" end filter_header= "Результат пошуку для умови:\n" + filter_header + "\n" if filter_header.length>0 h[:filter]=filter_header h[:data]=data pdf = OrderPdf.new(h) send_data pdf.render, filename: "sklad_tovar.pdf", type: "application/pdf", disposition: "inline" end end end |
Посилання:
Ruby on Rails – Railscasts PRO #153 PDFs with Prawn (revised)