Sunday, May 15, 2016

Build your own social media sharing buttons

I cobbled together a couple of share buttons for Facebook and Twitter for a WordPress site. I'm, obviously (as I still use the Blogger platform), not the biggest fan of WordPress - although it is huge, so... anyway. The idea was to get some consistent looking buttons into some part of a theme. I put the following into a 'Text widget', which allows you to inject arbitrary Text or HTML within some container within a theme:


So in order to use the above you are going to need to sign up for the Facebook apps service and if you want to prepopulate your Twitter handle, you will need your Twitter username as well.

It looks something like this:


Wednesday, May 11, 2016

How to create a watermark in Prawn (the Ruby library for writing PDFs)

 Prawn::Stamp is no good since, since you have to specifically call it for each instance of use, and you won't necessarily know how many pages you are going to get if generating the PDF dynamically from user generated content.

If you use #repeat, this method is going to write over existing text/drawings towards the end of PDF generation. But a watermark should be in the background, not 'stamped' on top.

Here's the solution:

  def watermark(watermark)
    function = lambda {@pdf.formatted_text_box([{:text => "#{watermark}", :color => '5B5B5B', :size => 60}], :rotate => 30, :rotate_around => :center, :align => :center, :valign => :center)}
    # call the function for the first page
    function.call
    # call the function for every subsequent page that is created
    @pdf.on_page_create {function.call}
  end


The method lets you use any string and centres it in the middle of the page irrespective of length.

Calling the function with #on_page_create ensures that the watermark is drawn first; other objects are then drawn on top.

Now watermark("Draft"), for example, can be used in any Prawn::Document.

Monday, February 01, 2016

Creating and manipulating pdfs in the Ruby on Rails framework

Whatever ones feelings on pdf, many people still find security in it as a replacement for paper. Pdf is widely used to store electronic copies of physical documents and transmit electronic flyers and brochures. Many people still print documents instead of keeping them on screen. Often, the file being printed will be in pdf. Pdf files continue to be relevant.

What sorts of things do we want to do with pdf? Here are some ideas:

  1. create reports
  2. replace html views with a pdf option (for ease of printing)
  3. concatenate pdfs
The following goes into limited detail on libraries available for a Ruby on Rails application.

1. Create reports
Prawn does the job. It is possible to stay DRY by collecting common elements to your reports such as a header, footer, divider or currency display helper in one file stored as a class e.g. ReportElements. You can then instantiate a new object taking from this class and use the methods contained within. If you need to change your header, then you only need to change one file.

2. Replace html views with a pdf option
Wicked PDF does this. If you want a higher level of control, then Prawn is a better option for generating reports. This way you can leave web pages to be more interactive and reports to be static. A good use case for Wicked PDF is a website' terms of service and other legal documentation. It's important to have only one file where the terms of service are updated to avoid spotting the difference. Wicked PDF parses the html and dynamically generates a pdf based on it.

3. Concatenate pdfs
CombinePDF seems to be a good option.

Putting it all together in a controller you could do something like this:

def complicated_pdf  
  @model = Model.find params[:model_id]  
  respond_to do |format|  
    format.pdf do  
      # get Prawn document  
      pdf_1_data = ExamplePrawnPdf.new(@model, current_user, view_context).render  
      pdf_1 = CombinePDF.parse(pdf_1_data)  
      # get the terms of service through wkhtmltopdf shell utility and WickedPdf gem  
      pdf_2_data = render_to_string pdf: "", file: "#{Rails.root}/app/views/home/terms_of_service.erb", encoding: "UTF-8"  
      pdf_2 = CombinePDF.parse(pdf_2_data)  
      combined_pdf = CombinePDF.new  
      combined_pdf << pdf_1  
      combined_pdf << pdf_2  
      send_data combined_pdf.to_pdf,  
        filename: "Complicated_report_#{@model.some_unique_identifier}.pdf",  
        type: "application/pdf",  
        disposition: "inline"  
    end  
  end  
end