A Simple Way to Generate formatted PDF Documents

written by amcvega on November 23rd, 2007 @ 12:37 AM

The Problem

Most of the applications we make are in aid of current manual systems. The whole reason clients come to us is because they want to streamline and automate parts of their processes but they still have to deal with the reality of the current, paper-based way of doing things. So it happens that recently I’ve gotten a sudden influx of requests to be able to generate printable pre-filled forms.

There are multiple ways to go about doing this. The easiest way would’ve been to just allow the user to click ‘print’ on their browser and serve them a formatted print.css page. However, a couple of projects back we ran into a problem using this approach – we could never get the same result across multiple computers. We tried restricting the browsers used to firefox but even that didn’t play nice with the differing operating systems. Using CSS to generate printable forms wasn’t an option.

The next ideal way would be to be able to generate a pdf using from an html output. This would be great because we could maybe use the existing templates and just generate the pdf from that. After looking around a while it seemed that PrinceXML was the way to go. Unfortunately for me, it didn’t come free. Alternatives such as HTML Doc just didn’t cut it.

Next in my quest was pdftk I thought maybe I could just design the templates by hand using Scribus and then just fill_form the values using pdftk. Again I hit a roadblock when I found that some of the forms had dynamic content (e.g. tables) that couldn’t be handled by this approach.

I was back to using PDF::Writer. The problem with pdf-writer is that it’s pretty raw. It allows you to do a lot of things with PDFs but you have to deal with lines, points, x/y coordinates, and all of the details. I didn’t have the time nor the patience to deal with all that for the amount of printables that were coming in.

The Solution?

So I decided to write my own little library that would fix all that. Introducing PDF::Cell – it’s a library based on PDF::Writer that allows you to layout documents in a straightforward manner without thinking about the nitty-gritty details about how exactly to position the elements. The model for laying out stuff is loosely based on Ruby Shoes’s concept of stacks and flows. Here’s an example:

pdf = PDF::Writer.new biodata = PDF::Cell::Base.new(pdf) biodata.build :width => 500, :font_size => 8 do header "Crew File #245: Jack Black (2/M of MV Nautilus)", :shaded => true, :font_size => 15 desc "The Content" cell :width => 375 do cell :width => 125 do text "<b>Given Name</b>" text "Jack" end cell :width => 125 do text "<b>Middle Name</b>" text "James" end cell :width => 125 do text "<b>Family Name</b>" text "Black" end cell :width => 250 do text "<b>Address</b>" text "#124 Main Street" end cell :width => 125 do text "<b>Contact No</b>" text "123-456-789" end end cell :width => 125, :height => 125 do text "Photo Here" end end

And here’s the result of the above code

Now for the explanation. The overall box is given a width of 500. (it uses pdf-writer’s measurements not mine) The width is strict – meaning everything else will adjust, just not the width. We add a cell to the box with 375 width – let’s call this the “Content” box. Within the Content box we add 3 cells each with a width of 125. These 3 boxes add up to exactly 375 – the limit of the Content box. Then we add another cell with a width of 250. Clearly this won’t fit into the Content box’s width so PDF::Cell automatically puts it below the previous 3 cells! And that’s basically it. Using that simple concept of cells you can potentially generate any layout your document needs.

I recently added support for tables within cells. Images within cells are coming up shortly although, if you know how to use pdf-writer, you can hack it yourself for now.

Installation

To install just copy/paste the following into your rails root directory:

ruby script/plugin install svn://svn.upstrat.com/plugins/pdf_cell/trunk

That’s it! You should be ready to go.

Speeding up Ruby with Lua

written by amcvega on November 4th, 2007 @ 12:00 AM

Everyone knows ruby is slow. That’s why I find that the ruby community is more obsessed with optimization than any other. One of the solutions tossed around to improve the performance of ruby programs is to forgo ruby in the complex computations and switch to C.

I don’t doubt this will work. In fact, based on all the stuff I’ve read, this is really a great way to speed up your app while still using the wonder (and joy) that is ruby. However I am loathe to go back to C. I mean, the whole reason I moved to ruby was because I wanted to use a high-level language and all the cool concepts not available to lower level languages.

Enter Lua. I’ve been reading about Lua for a while now. I know it’s fast ; it’s used in WoW and a whole lot of other stuff. It’s also a high level language which I find has a lot in common with lisp (something I’ve always wanted to learn). It’s also designed to be embedded into applications; much the same way ruby was initially designed as a tool for admins. It got me thinking that maybe Lua can help me speed up Ruby.

I found a nifty little library that allows lua to be called from within ruby called rubyluabridge. I installed it on my machine and decided to run the classic fibonacci benchmark test.

Code

fib.rb t = Time.now def fib(n) if n == 1 or n == 2 return 1 else return fib(n-1) + fib(n-2) end end answer = fib(ARGV[0].to_i) puts "Answer: #{answer}" puts "Calculation Time: #{Time.now - t}" new_fib.rb t = Time.now require 'rubyluabridge' l = Lua::State.new l.eval <<-LUA_END function fib(n) if n == 1 or n == 2 then return 1 else return fib(n-1) + fib(n-2) end end LUA_END l.eval "answer = fib(#{ARGV[0]})" puts "Answer: #{l.answer.to_i}" puts "Calculation Time: #{Time.now - t}"

Here are the results:

fib.rb 20
Answer: 6765
Calculation Time: 0.071339
new_fib.rb 20
Answer: 6765
Calculation Time: 0.034658
fib.rb 33
Answer: 3524578
Calculation Time: 11.272733
new_fib.rb 33
Answer: 3524578
Calculation Time: 2.103146

Conclusion

There is definitely an improvement in the processing time of the app with lua embedded. This is more apparent the more complex the calculation.

But the most striking thing is that there is very little change in the syntax of the code. If you’ll look at the embedded lua function fib(), it is almost identical to the ruby original. We got all that speed (around 500% in this example) for code that is essentially similar. I find it looks a lot better then lisp. (parentheses anyone?)

So there you have it, embedding lua into ruby for a quick performance boost.

Two-factor Authentication

written by amcvega on October 29th, 2007 @ 05:55 PM

Website authentication is usually done with using the username-password model: The user has a unique username and a password to prove that he owns that username. The programmer and the system administrator can put in all the encryption and security updates they can but if a hacker somehow manages to access a username and password (e.g. admin / password) then all the other measures become useless.

Enter multifactor-authentication. One-factor authentication is something you know – your username and password. The second factor is usually something you have – some form of key. On the web, it is not so easy to implement two-factor authentication. Usually, what passes for two-factor authentication doesn’t quite cut it.

There is an interesting idea out there though that aims to solve this called BeamAuth The idea is simpe – use bookmarks as a key. Using a little javascript, a bookmark, and the little-known fragment identifier, Ben Adida has developed a system that allows the user to securely send an encrypted key along with the login information. Seamless two-factor authentication!

BeamAuth is a new idea and I haven’t heard of any sites that use it yet. Unfortunately the demo app doesn’t work right now so I haven’t really seen it in action. However, the idea is simple and it looks easy enough to implement. I haven’t seen any holes in the idea yet maybe Bruce Schneier or Steve Gibson would know better but I don’t think they’ve heard of the idea yet. I might try it out myself soon and see if it’s as effective as it seems.

And...We're Back

written by amcvega on October 25th, 2007 @ 05:55 AM

Wow. Can’t believe it’s been months since we last updated the blog. We’ve been very busy. Well, I think we’ve got things more or less under control now and we can go back to blogging. Stay tuned!

Ruby Presentation in Malaysia

written by amcvega on May 16th, 2007 @ 03:00 AM

I recently went to Malaysia to do a quick workshop on Ruby on Rails for the Open Source Health Care Alliance. Presenting with me was Aizat. I think the workshop went well. Here’re the slides.

Trouble with RSpec Controller Specs

written by Cyx on April 23rd, 2007 @ 10:25 AM

I had a lot of head scratching just moments ago. Basically it had something to do with controller specs and our in-house plugin ActiveCRUD.

What happens is when you do something like :

context "the Category create page" do controller_name :categories specify "should render new if parameters are invalid" do post :create, :category => valid_category(:name => nil) response.should render_template(:new) end end

You aren’t able to even reach response.should render since doing the post :create will raise the exception.

What happens in our plugin is the same with most of beast-inspired applications. You have code like

def create @category.attributes = params[:category] @category.save! redirect_to category_path end private def rescue_action(exception) # render invalid model here, etc end end

But rSpec happily overrides the controller’s rescue_action method, which means all the expectations we have from our rescue_action are gone.

Right now I did some tweaks to our plugin, catching the exception manually and calling rescue_action_with_validation and then using alias_method_chain.

Hopefully I’ll have a more elegant solution in the future. But hey, they say that tests transform our code into more manageable pieces. I hope that’s what’s happening now.

Valid Model Parameters

written by Cyx on April 22nd, 2007 @ 09:55 AM

While writing tests in rails, we frequently use the pattern :

@article = create_article(:title => nil) @article.should have_at_least(1).error_on(:title)

and in the bottom of the test, we define a create_article. For the next model, say Project, you define also another one in the bottom.

Previously at our company, we’ve been extracting most of our valid model parameters into a module like so

module ValidParameters def valid_article { :title => 'My Article' } end end

Which is very useful when you need to create a model, and the last thing we want is unnecessarily having DAMP code.

But what of combining the two approaches?

I just created a module, which I’ll extract to a plugin at a future date which does exactly that. Basically you add parameters with a DSL-like syntax :

module ValidParameters valid :article, :title => 'My Article' valid :project, :name => 'Hedgehog', :owner_id => 1 end

and in your tests you can then do either :

post :create, :article => valid_article

or

lamba { create_article }.should have_difference(Article, :count)

or finally with invalid parameters

lambda { create_article(:title => nil) }.should_not have_difference(Article, :count)

Neat huh?

Safari http-accept-language

written by Cyx on April 11th, 2007 @ 08:28 AM

Recently I’ve been working with a Globalized rails application. I’ve been testing the app heavily, and often bouncing back between internet explorer and Firefox in order to make sure things are working.

After my latest upload though, the client said that the application was throwing an application error. I asked which page. He said the homepage. That made me wonder a lot.

After some hours I suddenly realized that maybe he was using Safari or some other browser. So I tried safari. There it was. The application error.

It boiled down to the ff lines of code:

request_language = request.env['HTTP_ACCEPT_LANGUAGE'] request_language = request_language.nil? ? nil : Locale.normalize(request_language[/[^,;]+/])

What happens is in Firefox the HTTP_ACCEPT_LANGUAGE is in the format

en-us,en;q=0.5

Whereas in safari, its just a plain en.

I added an additional case checking if the string matches two chars in the iso format. Hope this works for all browsers, will have to check Opera and Konqueror probably, which I’ve added somewhere in my personal todolist

Rethinking Deployment Strategy

written by Cyx on March 25th, 2007 @ 11:27 AM

Currently on one of the servers where we deploy rails, we use the Apache + Nginx + Mongrel setup, primarily for the following reasons :

  1. The Server has apache 1.3 already, and it’s really a pain to try updating it since it’s all tied up to cpanel
  2. Apache 1.3 proxying doesn’t support the ! directive, which basically is the strategy for skipping static images
  3. Because of the reason above, we use mongrel both for clustering and static file sending support.
  4. Mongrel, for obvious reasons, best of which is ease of use and deployment.

Now I’m thinking of just Apache + Mongrel, with no send file support. Basically the setup will rely on using rails’ asset host feature. Will post back if this works.

Also, im thinking of using pen as a load balancer, for ease of use and simplicity of getting it up and running (nginx config is a pain compared to pen)

Best Authorization Plugin for Rails

written by Cyx on March 21st, 2007 @ 03:42 AM

Ok, I think I’ve finally seen the authorization which fully satisfies my DSL taste.

Head on over to http://www.writertopia.com/developers/authorization to see what i mean.

Basically it allows you to define authorization

  1. Globally (throughout the entire app)
  2. For one model class (i.e. Group, Article)
  3. For an instance of the model class.

In addition, it features grammars!

(taken from the site : )

< checking out to read the source… >

Pretty Restful Resources

written by Cyx on February 21st, 2007 @ 09:53 PM

Have you ever questioned the rails way? We have.

http://mydomain.com/articles/1;edit

I’ve always had an itchy feeling when coding for this kind of URL ever since restful rails got out. Looking into resources.rb, we came up with a plugin that makes that URL look like this :

http://mydomain.com/articles/1:edit

So far, we haven’t had any problems yet. Nesting doesn’t also reveal any problems. We have declarations like :

map.resources :admin do |admin| admin.resources :products, :name_prefix => 'admin_' do |product| product.resources :sections, :name_prefix => 'admin_products' end end

Nothing seems to be broken as of now.

If you’re interested, check out the plugin @ svn://svn.upstrat.com/plugins/pretty_resources/trunk

Back to Nginx

written by Cyx on February 11th, 2007 @ 01:24 PM

After much head scratching, I just realized after re-reading the specs of mod_proxy in 1.3 spec that the mod_proxy version for apache 1.3.x doesn’t support the style

ProxyPass /images !

Looking closely at the spec

Syntax: ProxyPass path url Default: None

vs this one (in the 2.0 spec)

Description: Maps remote servers into the local server URL-space Syntax: ProxyPass [path] !|url

pretty much shows the unobvious difference that there is an exclamation point for v2.0 onwards.

With all that, I have opted to return to nginx (at least for now) with the new setup. Right now everything seems blazingly fast (and nginx has a new release, surprise surprise) so at long last, mongrel is no longer serving static files..

"Compiling" Ruby

written by amcvega on November 21st, 2006 @ 04:36 PM

We mostly deal with server-side applications. However, every so often someone comes up to us and asks if we can create and install an application on their PC. This used to present us with a bit of a dilemma since server-side applications are by nature, not that easy to install. This is usally okay since you’re really only going to be doing it once. Client-side applications on the other hand have to be really easy setup to use. Here are some of the requirements for distrubting an app:
  1. You cannot have the customer setup their own database on their computer
  2. You can’t have the customer install their own webserver
  3. You definitely cannot have the customer install the compiler/interpreter that you need to run your application.
  4. You cannot have the customer click more than one thing. (Anymore than one click, and things start to get really messy)

We’ve discovered the first steps to a solution to this dilemma for our rails apps thanks to a fascinating project on distrubuting ruby applications and another one for rails applciations. It’s not perfect but it’s good enough until we hear something from the JRuby, XRuby, Rite, or YARV projects along the lines of an actual compiler for ruby.

They’re pretty straightforward guides to “compiling” your ruby application here are a few lessons learned in our foray into this brave new world:
  • Make sure you use a portable database solution like SQLite. Everything is stored in one file and you can easily ship it with your app
  • Take a second look at your applcation if it has file-upload features.
  • Thank the man. It’s people like him that make the world a better place.

Lists!

written by amcvega on November 20th, 2006 @ 05:47 PM

People deal with a lot of things. Everyday, life make demands of us that sometimes just drive us crazy. But for some reason, We cannot escape it. It is ingrained in today’s society to handle many things at a time. in fact, productivity and efficiency have almost been synonymous with the ability to multitask.

I’m not going to write about doing less or simplifying life. Sometimes that’s just not possible. We want to make the best of everyday and so we have to tackle a lot of things. It’s the ability to do many things that make us such amazing beings.

Today’s little article is about lists. I’m a software developer and my life revolves around projects, feature requests, bugs, tasks, enhancements, and whatnot. You can begin to see that even my focused little nook of the world is riddled with its own barrage of todos and problems. It could literally drive programmers crazy. The only solution that I can think of is so simple that many don’t do it – make a list.

Lists are wonderful things.
  1. They remind you of the stuff you need to do.
  2. They keep you focused on the things you really need to be doing.
  3. They help set your priorities as you constantly reorder and reorganize them as new information arises.
  4. Last, and my favorite, it feels oh so good when you cross-off an item from your list.

The important thing is to keep it organized and up to date as new issues arise. If you don’t believe me, take it from a battle-hardened software guru .

I’ll stop yapping now, (I’ve got some stuff to do) but I’ll leave you with a great (and old) anecdote concerning this particular topic:

A man approached JP Morgan, held up an envelope, and said, “Sir, in my hand I hold a guaranteed formula for success, which I will gladly sell you for $25,000.” “Sir,” JP Morgan replied, “I do not know what is in the envelope, however if you show me, and I like it, I give you my word as a gentleman that I will pay you what you ask.” The man agreed to the terms, and handed over the envelope. JP Morgan opened it, and extracted a single sheet of paper. He gave it one look, a mere glance, then handed the piece of paper back to the gent. And paid him the agreed-upon $25,000.

The Paper:
  1. Every morning, write a list of the things that need to be done that day.
  2. Do them.

Ruby, Gtk, and Windows

written by amcvega on October 29th, 2006 @ 09:33 PM

I hate to admit it, but I’ll come clean. I have a Windows laptop. Hopefully that will change soon. In the meantime however I will have to make do with some problems of using Windows. One of these annoyances is getting ruby and gtk to work.

It’s not really a problem. You just have to dig a little to get it right, but just to make sure I don’t forget, here’s a little reminder for all those of you who want to run Ruby-Gtk in Windows.

First, go to the official ruby-gtk project and read a little.

Second make sure you read the bottom part concerning iconv.dll and it’s evil twin brother in your ruby_install_dir

Third, don’t forget the Gtk.init when you’re doing the third suggested test. You might be splitting hairs for no reason.