PDF Writer gem does not support special characters - ruby

Why the pdf writer does not support the special characters and russian,chinese letters using ruby

It true that pdf writer does not UTF-8 but you can implement you solution like following
Overriding PDF::Writer text method
Put the following code in a file called pdfwriter_extensions.rb (or whatever you choose to call it) in your lib directory:
CONVERTER = Iconv.new( 'ISO-8859-15//IGNORE//TRANSLIT', 'utf-8')
module PDF
class Writer
alias_method :old_text, :text
def text(textto, options = {})
old_text(CONVERTER.iconv(textto), options)
end
end
end
In your controller that handles the PDF output you add:
require 'pdf/writer'
require 'pdfwriter_extensions'
after which you can use PDF::Writer like in the tutorial:
pdf = PDF::Writer.new
pdf.select_font "Helvetica", :encoding => nil
pdf.text "User name: <b>#{#user.name}</b>", :font_size => 16, :justification => :left
send_data pdf.render, :disposition => 'inline', :filename => "user_details.pdf", :type => "application/pdf"
N.B: I have taken this solution from https://www.peterkrantz.com/2007/utf8-in-pdf-writer/

Related

Unable to upload images from Ruby to Wordpress using XMLRPC - damaged image

I am using a gem called rubypress to post content from ruby to wordpress using XMLRPC. Everything is working except for the image uploading part. I converted the image to base64 encoded format but after upoloading, all i get is a grey image and not the one that i had intended to upload(I am using smaller images around 100kb size to upload for testing). What I am i doing wrong?
Here's the code from rubypress github page(https://github.com/zachfeldman/rubypress) for uploading:
FILENAME='myFile.png'
wp.uploadFile(:data => {
:name => FILENAME,
:type => MIME::Types.type_for(FILENAME).first.to_s,
:bits => XMLRPC::Base64.new(IO.read(FILENAME))
})
Try:
wp.uploadFile(:data => {:name => File.basename(FILENAME),
:type => MIME::Types.type_for(FILENAME).first.to_s,
:bits => XMLRPC::Base64.new(File.open(FILENAME).read)
})
I was finally able to solve it by changing the Base64 encoding code as follows:
$wp.uploadFile(:data => {
:name => File.basename(imgname),
:type => MIME::Types.type_for(imgname).first.to_s,
:bits => XMLRPC::Base64.new(File.open(FILENAME,"rb").read),
:post_id =>postid
})
The file apparently needs to be "opened" first rather than be read using IO.read(FILENAME).
Here is my way of doing it, works pretty well:
image = MiniMagick::Image.open(this_image.path)
image.format('jpg')
image.combine_options do |c|
c.strip
end
image.write(this_image.path)
# most efficient resize as suggested by https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/
MiniMagick::Tool::Mogrify.new do |mogrify|
mogrify.filter('Triangle')
mogrify.define('filter:support=2')
mogrify.thumbnail('960x')
mogrify.unsharp('0.25x0.08+8.3+0.045')
mogrify.dither('None')
mogrify.posterize('136')
mogrify.quality('82')
mogrify.define('jpeg:fancy-upsampling=off')
mogrify.interlace('none')
mogrify.colorspace('sRGB')
mogrify << this_image.path
end
type = image.mime_type
bits = XMLRPC::Base64.new(IO.read(this_image.path))
begin
result = wp.uploadFile(
data: {
name: image_name,
type: type,
bits: bits,
post_id: post_id,
overwrite: true
})
rescue StandardError => e
puts e
end

Using Ruby CSV header converters

Say I have the following class:
class Buyer < ActiveRecord::Base
attr_accesible :first_name, :last_name
and the following in a CSV file:
First Name,Last Name
John,Doe
Jane,Doe
I want to save the contents of the CSV into the database. I have the following in a Rake file:
namespace :migration do
desc "Migrate CSV data"
task :import, [:model, :file_path] => :environment do |t, args|
require 'csv'
model = args.model.constantize
path = args.file_path
CSV.foreach(path, :headers => true,
:converters => :all,
:header_converters => lambda { |h| h.downcase.gsub(' ', '_') }
) do |row|
model.create!(row.to_hash)
end
end
end
I am getting an undefined method 'downcase' for nil:NilClass. If I exclude the header converters then I get unknown attribute 'First Name'. What's the correct syntax for converting a header from, say, First Name to first_name?
After doing some research here in my desktop, it seems to me the error is for something else.
First I put the data in my "a.txt" file as below :
First Name,Last Name
John,Doe
Jane,Doe
Now I ran the code, which is saved in my so.rb file.
so.rb
require 'csv'
CSV.foreach("C:\\Users\\arup\\a.txt",
:headers => true,
:converters => :all,
:header_converters => lambda { |h| h.downcase.gsub(' ', '_') }
) do |row|
p row
end
Now running the :
C:\Users\arup>ruby -v so.rb
ruby 1.9.3p448 (2013-06-27) [i386-mingw32]
#<CSV::Row "first_name":"John" "last_name":"Doe">
#<CSV::Row "first_name":"Jane" "last_name":"Doe">
So everything is working now. Now let me reproduce the error :
I put the data in my "a.txt" file as below ( just added a , after the last column) :
First Name,Last Name,
John,Doe
Jane,Doe
Now I ran the code, which is saved in my so.rb file, again.
C:\Users\arup>ruby -v so.rb
ruby 1.9.3p448 (2013-06-27) [i386-mingw32]
so.rb:5:in `block in <main>': undefined method `downcase' for nil:NilClass (NoMethodError)
It seems, in your header row, there is blank column value which is causing the error. Thus if you have a control to the source CSV file, check there the same. Or do some change in your code, to handle the error as below :
require 'csv'
CSV.foreach("C:\\Users\\arup\\a.txt",
:headers => true,
:converters => :all,
:header_converters => lambda { |h| h.downcase.gsub(' ', '_') unless h.nil? }
) do |row|
p row
end
A more general answer, but if you have code that you need to process as text, and sometimes you might get a nil in there, then call to_s on the object. This will turn nil into an empty string. eg
h.to_s.downcase.gsub(' ', '_')
This will never blow up, whatever h is, because every class in ruby has the to_s method, and it always returns a string (unless you've overridden it to do something else, which would be unadvisable).
Passing :symbol to :header_converters will automatically convert to strings to snake case as well.
options = {:headers => true,
:header_converters => :symbol}
CSV.foreach(filepath, options) ...
#<CSV::Row first_name:"John" last_name:"Doe">
#<CSV::Row first_name:"Jane" last_name:"Doe">

Prawn PDF: create a template without the default page

I want to create a document with prawn one or more pages long that uses a different template for each page.
Prawn::Document.generate("test.pdf") do
doc.faces.each do |face|
start_new_page(:template => face.background_path)
end
end
This works and creates a document, however the first page is a blank letter sized page and then my pages added with start_new_page show up. Is there a way to have prawn not generate that first page?
thanks!
pdf = Prawn::Document.new(:skip_page_creation => true)
doc.faces.each do |face|
pdf.start_new_page(:template => face.background_path)
< your page building code here >
end
should work if I'm reading the docs correctly.
My controller code looks like:
def pdf
#person = Person.find(params[:id])
send_data #person.as_pdf, :filename => "#{#person.pdfName}.pdf", :type => "application/pdf"
end
and the as_pdf method in person.rb looks like
def as_pdf(type = 'short')
pdf = Prawn::Document.new(:margin => [36, 36, 36, 36] )
driver = self.pdf_layout_info
driver.each do |element|
< lots of ugly layout logic >
end
pdf.render
end

Does a Markdown parser exist that can also generate Markdown in Ruby?

I want to parse a Markdown document so I get a tree structure that I am able to manipulate. Afterwards I want the output to be Markdown again.
Example:
# This is a title
And a short paragraph...
m = SomeLib.parse("# This is a tit...")
m.insert(1, "Here is a new paragraph") # or something simmilar
m.to_md
Should become
# This is a title
Here is a new paragraph
And a short paragraph...
As I want to heavily change the document I do not want to use REGEX or simillar techniques.
I looked into Maruku and BlueCloth but somehow I cannot generate Markdown again.
Probably not out of the box, but using redcarpet you could write a custom renderer to build your tree and then manipulate it.
Though beware in this case you can't reuse the Markdown and Renderer instance and all methods in the custom Renderer subclass are supposed to return a string. Something like this could be a starting point:
class StackRenderer < Redcarpet::Render::Base
attr_reader :items
def initialize
super
#items = []
end
def header(title, level)
items << { :text => title, :level => level, :type => :header }
"#{'#' * level} #{title}\n\n"
end
def paragraph(text)
items << { :text => text, :type => :paragraph }
"#{text}\n\n"
end
end
# example...
sr = StackRenderer.new
md = Redcarpet::Markdown.new(sr)
text = <<-EOF
# This is a title
And a short paragraph...
EOF
md.render(text) # => "# This is a title\n\nAnd a short paragraph...\n\n"
sr.items # => [{:type=>:header, :level=>1, :text=>"This is a title"},
# {:type=>:paragraph, :text=>"And a short paragraph..."}]

Error generating pdf using prawn

I am trying to use tags to give some styling for a pdf being generated using prawn. But, there seems to be an error.
require 'rubygems'
require 'prawn'
require 'prawn/layout'
require 'prawn/format'
Prawn::Document.generate "example.pdf" do
tags:h1=>{ :font_size => "16pt", :font_weight => :bold }
text"<h1>Student Details</h1>"
end
I get the following error -
/usr/lib/ruby/gems/1.8/gems/prawn-format-0.2.3/lib/prawn/format/text_object.rb:91:in `%': can't convert nil into Float (TypeError)
Any help is greatly appreciated.
Cheers!!
Shouldn't it be:
tags[:h1] = { :font_size => "16pt", :font_weight => :bold }
?
Also please note that:
As of Prawn 0.7, prawn-format is completely unsupported, and will not
work with versions of Prawn 0.7+. Feel free to fork and fix, of
course.
Consider using methods from Prawn::Text
http://rubydoc.info/gems/prawn/0.12.0/Prawn/Text
EDIT
For example:
require 'rubygems'
require 'prawn'
Prawn::Document.generate('font_calculations.pdf') do
font "Courier", :size => 16, :style => :bold
text "Student details"
font "Courier", :size => 12, :style => :normal
text "normal text"
text "this is normal, <b>but this is bold</b>", :inline_format => true
text "normal <font size='18'>bigger</font> normal", :inline_format => true
end
That's just one of many ways of doing this.

Resources