Sep19th

Importing multiple pdf pages and documents into PDFlib - Part 2

Nate Constant PDFLib, PDF, Rails, Ruby , , , Read on

This is a followup to my first post about importing multiple pages into PDFlib .
I have created a class that will allow you to import multi page PDF’s as well as importing multiple PDF documents into one generated PDF. It will also fill all of your PDFlib text blocks with the data you provide:

Please post any questions or comments about it.

Here’s the class on pastie: http://pastie.caboo.se/14052

Here’s the code:

# — HERE’S HOW TO USE THIS CLASS
# Created by Nate Constant, http://shabadeehoob.com . Please contact me if you need help using it
=begin
  1. open your PDF doc in Acrobat Standard (or Pro).
  2. using the PDFlib block tool draw your text blocks in your pdf where you want them
   a. if you are drawing blocks for checkboxes make sure to set the font to “ZapfDingbats” —IMPORTANT: dont use “Zapf Dingbats” <- see the space in there?
   b. if you are drawing blocks that are supposed to circle something (i.e. “circle your answer”) make sure to set the font size to something large to make the circle
  3. use the “Save As” to save your pdf into the directory you want (probably the directory in your rails app because you can access it via #{RAILS_ROOT})
  4. in this class go to the “fill_app”  method and set your “searchpath”. this is the path for your pdf doc in your rails app
  5. point your browser to the generate_pdf action and let er rip!
=end

class PdfDocsController < ApplicationController
  def generate_pdf
    @settings=Hash.new
    @settings[‘checkbox_type’] = “8″ # ZapfDingbats font number
    @settings[‘circlebox_type’] = “O”
    circle_type = “”
    @default_width = 612
    @default_height = 792
    @default_value = “n/a”
    @data = Hash.new(@default_value)

    @settings[“checkbox_type”] = “8″ #ZapfDingbats character number for checkbox
    @settings[“circle_type”]    = “O” #use this for circling answers

    # — NORMALLY YOU WOULD POPULATE THE @data INSTANCE VAR FROM A DATABASE OR SOMEWHERE ELSE
    @data[“male”]     = @settings[“checkbox_type”]
    @data[“name”]     = “Nate Constant”
    @data[“address”]  = “1234 some street”
    @data[“city”]     = “Denver”
    @data[“state”]    = “Colorado”

    send_data fill_app, :filename => “pdf_document.pdf”, :type => “application/pdf”,:disposition => “inline”
  end

  private
  def fill_app
    searchpath = #{RAILS_ROOT}/my_pdfs”

    p = PDFlib.new
    if (p.begin_document(“”, “compatibility = 1.6″) == -1)
      logger.info “Error: “ + p.get_errmsg()
    end

    # Set the search path for fonts and PDF files
    p.set_parameter(“SearchPath”, searchpath)
    p.set_parameter(“pdiwarning”, “true”)
    p.set_info(“Creator”, “businesscard.rb”)
    p.set_info(“Author”, “Your Name”)
    p.set_info(“Title”, “The title of your PDF”)

    #IMPORT YOUR PDF YOU CREATED WITH THE PDF BLOCK TOOL
    import_file(p,“answer_pleading.pdf”) 

    p.end_document(“”)
    p.get_buffer()
  end
  def import_file(p,filename)
    blockcontainer = p.open_pdi(filename, “”, 0)
    if (blockcontainer == -1)
      logger.info “Error: “ + p.get_errmsg()
    end

    regularfont = p.load_font(“Helvetica”, “winansi”, “”)
    checkbox_font = p.load_font(“ZapfDingbats”,“builtin”,“”)
    #loop through all pages and put data in the blocks
    number_of_pages = p.get_pdi_value(“/Root/Pages/Count”,blockcontainer,-1,0)
    1.upto(number_of_pages){|page_num|

        #get current page
        page = p.open_pdi_page(blockcontainer, page_num, “”)
        if (page == -1)
          logger.info “Error: “ + p.get_errmsg()
        end

        #get all blocks for the page and put them in an array to use later
        num_of_blocks_on_page = p.get_pdi_value(“vdp/blockcount”,blockcontainer,page,0)
        cur_blocks =  Array.new
        0.upto(num_of_blocks_on_page-1){ |i|
          cur_blocks.push( p.get_pdi_parameter(“vdp/Blocks[#{i}]/Name”, blockcontainer, page, 0))
          #logger.info p.get_pdi_parameter(”vdp/Blocks[#{i}]/Name”, blockcontainer, page, 0)
        }
        width = p.get_pdi_value(“width”,blockcontainer,page,0)
        height = p.get_pdi_value(“height”,blockcontainer,page,0)
        #set page size
        p.begin_page_ext(@default_width, @default_height, “topdown”)
        # This will adjust the page size to the block container’s size.
        orient =  width>height ? “orientate west” : “”
        p.fit_pdi_page(page, 0, @default_height, #{orient})

        # Fill all text blocks with dynamic data
        cur_blocks.each { |key, value|
          use_font = p.get_pdi_parameter(“vdp/Blocks/#{key}/fontname”, blockcontainer, page, 0)
          if use_font == “ZapfDingbats”#is this block a checkbox?
            font_string = “font #{checkbox_font.to_s} embedding encoding=builtin”
            @data[key] = “” if @data[key] == @default_value
          else
            font_string =“font #{regularfont.to_s} embedding encoding=winansi”
          end
          if (p.fill_textblock(page, key, @data[key].to_s,font_string) == -1)
            logger.info “Warning: “ + p.get_errmsg
          end
        }

        p.end_page_ext(“”)
        p.close_pdi_page(page)
    }#end looping through all of the pages
    p.close_pdi(blockcontainer)
  end
end

Update: Tony Buser has modified this code by making it into a hash object. View it here

Sep4th

Mongrel pid error fixed

Nate Constant Rails, Ruby, Mongrel , , Read on

I am BRAND SPANKIN NEW to mongrel and for a few days i could not figure out what an error was I was getting.

I have been setting up my mongrel to run off a config file so I would run this command from my rails app top level directory:

mongrel_rails start -G config/mongrel_production.yml -e production -p 8000 -d -l log/mongrel.log

and then I would start the mongrel with:

mongrel_rails start -C config/mongrel_production.yml

The first line above creates a file in config/ called mongrel_production.yml, it would set the port to 8000, the log file to log/mongrel.log, the mongrel to be a daemon process (running in the background), and would set it to production mode. The next line starts the mongrel.

Well the error I was getting happened when I wanted to stop the mongrel process:

mongrel_rails stop

the error would be:

!!! PID file log/mongrel.pid does not exist. Not running?
stop reported an error. Use mongrel_rails stop -h to get help.

I ended up communicating with Zed Shaw (who, from what i can tell is the creator of mongrel) and he said that they had some problems with the paths in version 0.3.13.3 and he recommended for me to use the latest pre-release of mongrel (which as of right now is 0.3.13.4). He told me to use this command to get the latest via gem:

gem install mongrel --source=http://mongrel.rubyforge.org/releases/

and what do you know? It worked!! now i can stop my mongrels with:

mongrel_rails stop

Sep4th

Typo, Work in Progress

Well, I figured that since I’m making a go at this Rails thing I might as well use the Rails-based Blogging platform, “Typo”:http://typosphere.org.

Before I get into any details I want to say that there are a ton of very nice features of Typo like live searching and Theme switching. One major thing I liked was the support for migrating my blog articles from WordPress 2.

I hope this doesn’t become a trend for me but I’ve labeled this article “Typo, Work in Progress” because I find myself with a few issues getting it going. I hope to find the answeres to my problems and then will post updates as i get them figured out.

So, I’ve made a lot of new changes lately in the web world.. I moved all of my sites to a new hosting provider “Rimuhosting”:http://rimushosting.com (who, by the way have been FANTASTIC in helping me setup my server with the things I wanted), I’m trying out a new server configuration (Apache2 proxied to Mongrel), new Blog app, among other things.

The reason i informed you about the changes is to say that one of my Typo problems may be stemming from the server config.

Let’s talk about some frusterations of Typo.

My first major thing is that the gem install of Typo requires sqlite2-ruby. Normally this would not be a big deal to me; I would just let it install the dependency and be on my way but for some reason my system gives an error when trying to install sqlite3-ruby and therefor i can’t install Typo via gem because of it. Who uses sqlite3-ruby anyway? :) No offense to anyone but i only plan on using MySQL. So the thing is, Typo supports MySQL right out of the box so why are they requiring sqlite3-ruby to be installed? I DON’T WANT TO! Ok, well that throws the gem install out of the window (for me at least). My second option is to unpack the compressed file and upload it. (Don’t ask why I didnt checkout the subversion trunk, I didn’t think of it until just now, maybe I will, shut up.) Ok, well things went smoothly after that fiasco. I FTP’d the typo directory up to my server and off I went.

I do have to say that (once installed), Typo was very easy to get up and running quickly.

Ok, so here’s my work in progress problem:

Like I said before, I’m using Apache2 proxied to mongrel (not cluster as of this time).

First, my blog seems to run much slower than the other Rails apps I have on the same server.

Second, If you open up the “Activity” window in Safari (Yes, I only use Mac OS X) I get an “internal server error” on many of the .gif’s that are loaded for my theme. Now, I know that the “internal server error” is a very generic error message and it doesn’t give any explanation but I can’t find the probem in the config files.

I looked in the error log files for Apache2, nothing. I set mongrel to Debug mode and those log files didn’t show anything either. I really dont know where to go to find the problem.

So, If you have ANY suggestions for me, I would appreciate it if you posted a comment, Hopefully I will find the answer soon and post it here for any of you with the same problem.