Rails: Generate QR Code in Prawn PDF - ruby-on-rails

I'm trying to generate a pdf document with different QRcodes and am using the following gems
gem 'prawn'
gem 'prawn-qrcode'
Issue is, I can't seem to print out the QRcode with the following method:
require 'prawn/qrcode'
class QrcodePdf < Prawn::Document
def initialize (deal)
super()
#deal = deal
title
#deal.venues.each do |venue|
text "QR Code for: #{venue.name}"
qrcode = RQRCode::QRCode.new(#deal.id.to_s + "_" + venue.id.to_s + "_" + #deal.created_at.to_s)
render_qr_code(qrcode)
end
end
def title
text "Title of deal: #{#deal.title}", size: 16, style: :bold
end
end
Any help will be appreciated! Thank you!
Edit: Additional Info
Sorry, i forgot to state that the pdf is actually being compiled. But the QRCode section is blank.
So it just print the text of QR Code for ... in the loop.
Also, I've printed out the string in #deal.id.to_s ... and it does contain the data I want, so I'm not sure what went wrong.
I've also refereed to https://github.com/jabbrwcky/prawn-qrcode in the usage section.

It's probably bug with prawn-qrcode, but render_qr_code is not working. At least for Ruby 2.2.3 (I didn't tested if for older versions).
Still you can use print_qr_code method and it's functional:
pdf = Prawn::Document.new(:page_size => "A4") do
print_qr_code("some-text", extent: 96, stroke: false)
end

Related

Validate PDF is stampable - Rails, Prawn, CombinePDF

I'm working at a company where we upload a good amount of PDFs, which we later stamp using Prawn. Occasionally these PDFs upload and save fine, but when we try to stamp them later they don't work and our managers have to re-convert the file, and re-input a bunch of data.
As such we're looking for ways to validate the PDFs before they're attached to ensure they're going to be stampable later, or convert them to a PDF format we know is going to work with Prawn.
I have two questions
is there anything wrong with our stamping code? (posted below)
is there any way to do that sort of validation? including
converting to a Prawn doc before uploading
converting to a Prawn doc and attempting some trivial operation before uploading
any other solutions
begin
paid_stamp_pdf_file = Tempfile.new('paid')
Prawn::Document.generate(paid_stamp_pdf_file.path) do |pdf|
if self.is_paid_by_trust? && self.submitted_to_trust_date.present?
text = "Submitted to Trust - " + self.submitted_to_trust_date.strftime('%m/%d/%Y') + "\nPAID #{Date.parse(paid_on_date).strftime('%m/%d/%Y')}" + " - $#{'%.2f' % amount}" + payment_method_text
else
text = "PAID #{Date.parse(paid_on_date).strftime('%m/%d/%Y')}" + " - $#{'%.2f' % amount}" + payment_method_text
end
pdf.transparent(0.6) do
pdf.fill_color "ff0000"
pdf.text text, :size => 30, style: :bold, align: :center, valign: :center
end
end
# Stamp "PAID" to every page of the file
paid_stamp = CombinePDF.load(paid_stamp_pdf_file.path).pages[0]
URI.open(self.account_statement_file.blob.url) do |tmp_pdf_file|
pdf = CombinePDF.load tmp_pdf_file.path
pdf.pages.each {|page| page << paid_stamp}
ActiveRecord::Base.transaction do
if pdf.save tmp_pdf_file.path
file_name = self.account_statement_file.filename
self.account_statement_file.purge
self.account_statement_file.attach(io: File.open(tmp_pdf_file.path), filename: file_name, content_type: 'application/pdf')
self.update(is_paid: true, paid_date: paid_on_date, marked_paid_by_user_id: user.id)
return true
else
return false
end
end
end
rescue Exception => e
Rails.logger.error("Failed to mark statement ID #{self.id}: #{e.message}")
return false
end
Any help is greatly appreciated!
ruby 2.7.2
rails 6.1.1
prawn 2.4.0
combine_pdf 1.0.21
Edit:
Was able to replicated error, trying to load from file url
Occurs at line
Same error occurs when trying to parse downloaded file
For anyone else who sees this it was related to CombinePDF only parsing until it reaches what the metadata says the length, but some files lie about that so it causes them to fail and produce a RangeError: index out of range. Adding this work around, then using the relaxed option it adds fixed the issues for me, hopefully it merges into the gem itself soon.
https://github.com/boazsegev/combine_pdf/issues/191

#<NoMethodError: undefined method `table' for #<PdfMethods:0x0000023fc7b70648>>

I have been trying to create a table in a pdf i am generating using Prawn gem in rails. I have been following some tutorial but when I try adding the table to the pdf I am getting the error '#<NoMethodError: undefined method `table' for #PdfMethods:0x0000023fc7b70648>'.
Here is my code:
require "prawn"
class PdfMethods < Prawn::Document
def initialize
super
pdf_text
statement_accounts
end
def pdf_text
text "Order goes here", size: 40, style: :bold
end
def statement_accounts
move_down 20
table_data = Array.new
table_data << [[1, 2], [3, 4]]
table(table_data)
end
end
I have already installed both the prawn and prawn-table gems. Any help will be appreciated.
For many years (like since 1.2, so 7, 8 years?), table support has been in another gem called prawn-table, you'll need to have that in your project too, then Prawn::Document supports the table method. Maybe get a newer tutorial? ;)

Saving hash as json and getting it back trouble in ruby on rails

I'm saving the result of this method to file in json format:
class VideosController < ApplicationController
...
def getting_hash
video = Video.new
video.id = 12
video.title = "How to make it work?"
video.desc = "No idea..."
video_hash = Hash.new
video_hash[video.id] = {id: video.id, title: video.title, desc: video.desc}
write_to_file(video_hash)
end
...
end
So for saving to the file I use:
def write_to_file(model)
path = "#{Rails.root}/public/my_file.cache"
open(path, 'w') { |f|
f.write(model.to_json)
}
end
Seems like vanilla, but when I use:
read_from_file(my_file.cache)
def read_from_file(file_name)
path = Rails.root + "public/#{file_name}"
file = File.read(path)
hash_to_return = JSON.parse(file)
end
It returns not the hash, but an array!
NoMethodError (undefined method `id' for #<Array:0x007f1926325460>):
And when I check:
["12", {"id"=>"12", "title"=>"How to make it work?", "description"=>"No idea..."}]
I don't understand how is that possible, because if I use variables it makes everything perfect like:
(byebug) test = {"12":{"id":12,"title":"How to make it work?","desc":"No idea..."}}
{:"12"=>{:id=>12, :title=>"How to make it work?", :desc=>"No idea..."}}
(byebug) test2 = test.to_json
"{\"12\":{\"id\":12,\"title\":\"How to make it work?\",\"desc\":\"No idea...\"}}"
(byebug) JSON.parse(test2)
{"12"=>{"id"=>12, "title"=>"How to make it work?", "desc"=>"No idea..."}}
Please, help me with getting correct hashes back! Any ideas are highly appreciated!
UPDATE
JSON::ParserError (lexical error: invalid char in json text.
{"12"=>{:id=>"12", :title=>
(right here) ------^
):
UPDATE 2
my_file.cache's output:
{"12":{"id":"12","title":"How to make it work?","description":"No idea..."},"14":{"id":"14","title":"Yoga","description":"Guide"}}
UPDATE 3
For now I've overriden this situation with: video_hash = Hash[*hash_to_return.flatten] and got the desired format.
So back home I'll try with running plain ruby file (as rwold said) and also I'll test the approach by ahmed eshra.
Sincere thanks to all who participated!
UPDATE 4
I tried my code as a plain ruby file outside Rails (with slight modifications) and it worked perfectly!
I think passing the object itself with to_json conversion, is better for what you need and it will be saved as hash.
def getting_hash
video = Video.new
video.id = 12
video.title = "How to make it work?"
video.desc = "No idea..."
# Removing the hash conversion step
write_to_file(video)
end

How do I add a QR code to table rows with Prawn and Rails 4

I am using the prawn gem with Rails 4
I have the following gems:
gem 'prawn'
gem 'prawn-table'
gem 'prawn-qrcode'
I get the following error:
Prawn::Errors::UnrecognizedTableContent
When I do this:
require 'prawn/qrcode'
class ReportPdf < Prawn::Document
def initialize(organizations)
super()
#organizations = organizations
table_content
end
def table_content
table organization_rows do
row(0).font_style = :bold
self.header = true
self.row_colors = ['DDDDDD', 'FFFFFF']
self.column_widths = [40, 300, 200]
end
end
def organization_rows
[['#', 'Name', 'id']] +
#organizations.map do |organization|
[render_qr_code(RQRCode::QRCode.new(organization.id.to_s)), organization.name, organization.id]
end
end
end
Can anyone help by providing an example of adding a QR code to each row in a table?
UPDATE:
I changed my table code to the following (I added .to_s to the qr code:
def organization_rows
[['#', 'Name', 'id']] +
#organizations.map do |organization|
[render_qr_code(RQRCode::QRCode.new(organization.id.to_s)).to_s,
organization.name,
organization.id]
end
end
Now, I get the following pdf. See screenshot. How can I get those QR codes inside of a table cell?
You currently use:
def organization_rows
[['#', 'Name', 'id']] +
#organizations.map do |organization|
[render_qr_code(RQRCode::QRCode.new(organization.id.to_s)).to_s,
organization.name,
organization.id]
end
end
This results in prawn-table to convert and render the QRCode as string.
By default tables accept he following data as table cells:
String: produces a text cell (the most common usage)
Prawn::Table::Cell
Prawn::Table
Array
Images
Unfortunately I don't have the time right now to really dig into this problem, but judging from the documentation at: http://prawnpdf.org/docs/0.11.1/Prawn/Table/Cell.html,
you most likely need to create a subclass of Prawn::Table::Cell, that renders the QR code by implementing the #draw_content() method.
You also might have to adjust/constrain the table cell dimensions to provide miminum size to fit the QRCode by implementing #set_width_constraints()

prawn pdf group, transaction and rollback method problems

I'm trying to create a pdf report using prawn in a rails application. There are lots of sections that contain user generated content that I want to try and group together. Sometimes this will go over more that one page which results in a cannot group error. I then tried to use a transaction so that in the event of an error I can rollback and then output the content without using the group method.
The problem is the rollback stuffs up the pages. It removes the extra page from the pdf but still has the wrong page count and outputs over lapping content when I try to redo it. I reset the y position after the rollback, as per the prawn documentation but I still get the problems.
eg. The following test code writes 2 pages of numbers, does a rollback to the start and then tries to write the same numbers again. It results in a single page pdf with the second page of numbers overlapping the first and a page count of 2. The page counts at the bottom of the page also overlap one another even though I'm using the prawn number_pages method
class TestReport < Prawn::Document
def to_pdf
font('Helvetica')
bounding_box([bounds.left, bounds.top - 50], :width => bounds.width, :height => bounds.height - 100) do
text 'begin'
y_pos = y
transaction do
begin
group do
64.times do|i|
text i.to_s
end
end
rescue
rollback
end
end
self.y = y_pos
64.times do|i|
text i.to_s
end
text 'end'
text page_number.to_s
end
page_numbers(1)
#render
end
def page_numbers(start)
string = "page <page> of <total>"
options = { :at => [bounds.right - 150, 40],
:width => 150,
:align => :right,
:start_count_at => start,
:color => "000000" }
number_pages string, options
end
end
def test_report
pdf = TestReport.new()
pdf.to_pdf
send_data pdf.render, filename: "test.pdf",
type: "application/pdf",
disposition: "inline"
end
The problems seem to be with transaction rollbacks. The main thing I want is to be able to use the group method. Is there another way?
Is my code wrong? Am I missing something or do transaction not currently work.
I'm currently using the master prawn branch in a ruby on rails application ( gem 'prawn', :git =>
'git://github.com/prawnpdf/prawn.git', :branch => 'master').
This question is quite old now, but I'll post an answer since it is one of the first hits on Google when searching for the exception.
Transactions still doesnt work with page breaks (v 1.0.0.rc2), so I created a helper method that tries to use grouping first and then if the exception occurs it just retries without grouping, making the content span more than one page.
def group_if_possible(pdf, &block)
begin
pdf.group { block.call }
rescue Prawn::Errors::CannotGroup
block.call
end
end
Example: Using it when creating a table:
group_if_possible(pdf) do
pdf.table(rows)
end
EDIT:
Grouping were removed from Prawn 1.x but there is an unofficial grouping gem that works well for Prawn 2:
https://github.com/ddengler/prawn-grouping
Looks like Brad Ediger answered your question on Google Groups, but for the benefit of anyone else looking for help with this, here's his response:
Sadly, transactions do not yet work correctly when they start new
pages or change the pages collection. It's a known issue:
https://github.com/prawnpdf/prawn/issues/268
-be

Resources