Announcing 'Princely' - Rails Prince XML PDF Wrapper

Posted by on December 20th, 2007.

Recently I was implementing PDF generation for a project utilizing the fantastic library Prince XML. I came across a blog article with a basic library and helper set for Prince, which provided a great basis. I wanted to make something a little more generalized and in-keeping the Rails Way, so I have created ‘Princely’, a simple wrapper utilizing much of the code from the SubImage library but giving it better helpers and pluginizing its inclusion.

Installation

The first step is to download Prince and install it on your platform of choice (only Linux and Mac OS X supported by the plugin at this time). Next, simply install the plugin:

script/install plugin http://svn.intridea.com/svn/public/princely

You are now ready to get started using Princely to generate PDF. Note that Princely is only compatible with Rails >= 2.0

Usage

Princely uses the MimeTypes and respond_to blocks from Rails 2.0 to add PDF as a render option and a format. Because of this, it’s incredibly easy to implement a PDF! Simply make your XHTML or XML template and use pdf as the format (e.g. show.pdf.erb), then add code similar to this in your controller:

class Page < ApplicationController
  def show
    respond_to do |format|
      format.html
      format.pdf { 
        render :pdf => @page.pdf_name,
               :template => "show.pdf.erb", # not required, shown for example
               :layout => false             # not required
      }
    end
  end
end

And that’s all there is to it! If you add a .pdf to your properly routed path, you should be presented with a PDF version of the page generated by Prince. The README has more detailed usage information.

As always, there is a Trac available for any bugs or patches you might come across.

Share:

Comment on this post (1 comment)


Team Intridea featured in eWeek

Posted by on December 16th, 2007.

Team Intridea has gained a national reputation for its team members' expertise and knowledge, especially when it comes to Ruby on Rails. Adam and Chris were recently interviewed for an eWeek.com article about Ruby on Rails 2.0 - check it out to see what they had to say:

Ruby on Rails 2.0 Users Give Thumbs Up

Share:

Comment on this post (0 comments)


Faking 'onpaste' in Firefox

When trying to find a solution for cleaning Rich Text pasting into a textarea, we needed to find a way to detect pastes and trigger an event based on said action. Internet Explorer and Safari both have an onpaste event that allows you to hook javascript into a paste event, but Firefox does not allow this.

After a little Googling, I didn’t really come across much of a solution so I decided to roll my own.

  function checkForPaste(event) {
    var e = event.element();
    if ((e.previousValue && e.value.length > e.previousValue.length + 1) ||
        (!e.previousValue && e.value.length > 1)) { 
      if (e.onpaste) {
        e.onpaste(e)
      } else if (e.readAttribute("onpaste")) {
        eval(e.readAttribute("onpaste"));
      }
    }
      e.previousValue = e.value;
  }

  function firefoxOnPaste() {
    $$('textarea').each(function(e) { 
      if (e.onpaste || e.readAttribute("onpaste")) {
        Event.observe(e,'input',checkForPaste);
      }
    });
  }

  if (Prototype.Browser.Gecko) {
    document.observe('dom:loaded', firefoxOnPaste);
  }

This snippet of code will automatically detect if an onpaste has been either added to a textarea’s attribute list (e.g. <textarea onpaste='alert("Pasted!")/>) or set programmatically. It will then automatically simulate paste detection using the oninput event and trigger the onpaste code when it believes a paste has been made.

The snippet will detect correctly for all pasting I’ve tried, including selecting a chunk and pasting a replacement. The only major caveat I’ve seen thus far is that the first input change after the page load will register as a paste if the textarea’s value has already been set. In any case, I thought it was a relatively straightforward way to solve the problem.

Share:

Comment on this post (0 comments)


Announcing 'Browserized Styles'

Browser compatibility, the web designer’s nightmare, has always seemed more difficult than it has to be. Why hasn’t there been an industry-standard, simple way to target CSS to specific browsers, allowing one to style the page properly without worrying about hacks and other difficult ways of pulling all the information together? I thought that something should be done about it, so taking Richard Livsey’s ‘browser_detect’ plugin as a starting point, I developed an automatic solution for including browser-specific stylesheets.

Browserized Styles provides a dead simple way to create browser-specific CSS code for use in a Rails application. All you need to do is create a .css file targeted to a browser by appending an underscore and identifier to the end.

Installation


script/plugin install http://svn.intridea.com/svn/public/browserized_styles

Example

Let’s say I have some complex CSS code that looks bad in some browsers, but works in others. Let’s also say that i’ve put it into a stylesheet in stylesheets/complex.css.

My stylesheet link tag looks something like this:


<%= stylesheet_link_tag 'complex' %>

Now all I have to do to target a browser is create a new CSS file with the browser’s identifier appended to it with an underscore (e.g. “complex_ie6.css”). That’s it! The same exact stylesheet link tag will automatically check the current user agent and load a browser-specific CSS file if it exists. Ta-da! One-step browser styles!

More information is available in the readme, but the end result is browser-targeting bliss.

The plugin is brand new and will probably see some modifications in the future. If you run into any problems or come up with a patch, feel free to submit it to the Intridea Public Trac .

Share:

Comment on this post (0 comments)


Announcing 'acts_as_taggable_on'

For a number of applications, especially our Social Networking Platform I’ve found a need for advanced tagging functionality not offered by the acts_as_taggable_on_steroids plugin. Namely, there have been a number of times when I’ve wished a model could have multiple “sets” of tags that would function both independently and together. For example, a user might have tagged themselves, but they might also have skills, interests or sports that would also function like tags. That’s where acts_as_taggable_on comes in.

Installation

To install the plugin on Edge Rails or Rails 2.1 and greater:

script/plugin install git://github.com/mbleigh/acts-as-taggable-on.git

On previous versions of Rails:

git clone git://github.com/mbleigh/acts-as-taggable-on.git vendor/plugins/acts-as-taggable-on

Usage

Acts As Taggable On provides the same functionality of acts_as_taggable_on_steroids with the addition of the notion of “contexts,” or scoped areas in which taggings can live. For the user example listed above, I can now simply make a call like so:

class User < ActiveRecord::Base
  acts_as_taggable_on :tags, :skills, :interests, :sports
end

By taking the same one-liner tack as previous implementations, we are now able to set, find, retrieve, and calculate information based on tags within a context as well as as a whole. With the user model we just created:

@user = User.new(:name => "Bobby")
@user.tag_list = "awesome, slick, hefty"      # this should be familiar
@user.skill_list = "joking, clowning, boxing" # but you can do it for any context!
@user.skill_list # => ["joking","clowning","boxing"] as TagList
@user.save

@user.tags # => [<Tag name:"awesome">,<Tag name:"slick">,<Tag name:"hefty">]
@user.skills # => [<Tag name:"joking">,<Tag name:"clowning">,<Tag name:"boxing">]

User.find_tagged_with("awesome") # => [@user]
User.find_tagged_with("joking") # => [@user]
User.find_tagged_with("awesome", :on => :tags) # => [@user]
User.find_tagged_with("awesome", :on => :skills) # => []

@frankie = User.create(:name => "Frankie", :skill_list => "joking, flying, eating")
User.skill_counts # => [<Tag name="joking" count=2>,<Tag name="clowning" count=1>...]

@bobby.skill_counts
@frankie.skill_counts

And that’s all there is to it! Now you can scope your tags to whatever arbitrary name you would like. The inflector is used to create the singular/plural methods, so be careful about making sure that your nomenclature uses plurals in the acts_as_taggable_on call.

As a side note, this is meant to be used in place of acts_as_taggable_on_steroids, and the acts_as_taggable method works in acts_as_taggable_on simply by calling acts_as_taggable_on :tags. Caching has been written into the implementation but is not yet tested or verified to be working. Stay tuned for additional improvements to this plugin, and feel free to submit any bugs or patches to the Lighthouse

UPDATE 5/3/07: Acts As Taggable on is now hosted on GitHub and has a public Lighthouse available for bug tracking. Information updated above.

Share:

Comment on this post (32 comments)