Enhanced Migrations v1.2.0

Posted over 6 years back at Revolution On Rails

The original release of this highly useful plugin marked a turning point in collaborative Rails development by freeing the developer to commit their database migration without fear of having it ignored because of a higher placed migration number. This latest release includes some minor bug fixes plus a useful method for stepping through migrations one at a time without the need for copying and pasting long version numbers.

  1. Fixed bug where an empty migrations_info table would create a non-parseable schema.rb.
  2. Made plugin database independent.
  3. Added capability to step through migrations using VERSION=[previous, next, first and last].
  4. dump_schema_information now returns all migrations, not just latest (credit to François Beausolei).
  5. Added tests which use SQLite and a task (enhanced_migrations:clean_sqlite_db) to help with testing.
As an example of item number three, consider the following situation. Using the enhanced migrations plugin, you've just created a migration that adds a new table to your database. Upon running it, you discover that you used the wrong data type for a column. Rather than having to copy and paste the previous migration's version number, simply using 'previous' in the VERSION number will now suffice.

rake db:migrate VERSION=previous
This also works using prev along with next, first and last for their respective operations. Keep in mind that first will go to the first migration and is not the same as VERSION=0.

Migrate as usual

shell> rake db:migrate
== CreateRecipesTable: migrating ==============================================
-- create_table(:recipes)
-> 0.0902s
== CreateRecipesTable: migrated (0.0904s) =====================================

== AddRecipesForUser1: migrating ==============================================
-- execute("INSERT INTO recipes (name, owner) VALUES ('Lemon Meringue Pie', 'user1')")
-> 0.3684s
== AddRecipesForUser1: migrated (0.5302s) =====================================

== AddRecipesForUser2: migrating ==============================================
-- execute("INSERT INTO recipes (name, owner) VALUES ('Steak and Kidney Pie', 'user2')")
-> 0.2574s
== AddRecipesForUser2: migrated (0.3962s) =====================================

Migrate to the previous version

shell> rake db:migrate VERSION=previous
== AddRecipesForUser2: reverting ==============================================
-- execute("DELETE FROM recipes WHERE owner = 'user2'")
-> 0.4512s
== AddRecipesForUser2: reverted (0.4516s) =====================================

Migrate to the first version

shell> rake db:migrate VERSION=first
== AddRecipesForUser1: reverting ==============================================
-- execute("DELETE FROM recipes WHERE owner = 'user1'")
-> 0.1676s
== AddRecipesForUser1: reverted (0.1678s) =====================================

Migrate another previous version, essentially the same as VERSION=0 since we are already at the first migration.

shell> rake db:migrate VERSION=previous
== CreateRecipesTable: reverting ==============================================
-- drop_table(:recipes)
-> 0.1680s
== CreateRecipesTable: reverted (0.1683s) =====================================

How to get
Download the gem from Rubyforge and install it like so:
sudo gem install enhanced_migrations-1.2.1.gem
Update - 11/15/2007
The previous version had a small bug that was discovered during use here that sometimes caused an app's database yaml file to be overwritten by the gem's database config which is used only for testing. The chances of this happening outside of our particular setup are small but we felt it warranted an immediate fix. We've also added a gzip'd source file for the plugin fans out there.

Links in the post have been updated to reflect the location of this new release.

Coming up for air

Posted over 6 years back at The Hobo Blog

The big app we’ve been working on over here is finally calming down. Not finished as such, but close enough that we can start to give some attention to the hundred other things we’ve got on the go, like… Hobo!

The first benefit will be that Hobo 0.6.3 is on it’s way. There are no huge new features, but lots of little touches. In all, over 100 commits since 0.6.2. I’ve just finished the changelog (which took ages!) so hopefully this will make it out of the door tomorrow.

And of course I haven’t forgotten all the docs I’ve been promising. There’s one fairly significant change on it’s way first though - we’ve figured out a way to merge the camel-case <TemplateTags> and <normal_tags> into one kind of tag, with two different styles for calling the tag. It’s going to be a big improvement to the aesthetics of DRYML code. And while we’re on aesthetics, we’ve decided to switch from <tags_with_underscores> to <tags-with-dashes>. Don’t freak out – we’re going to provide a rake task that will update your existing DRYML source automatically. We’ve got enough DRYML code ourselves to make it well worth the effort to write that utility.

Overall you can expect to see a general upturn in activity in the Hobo project over the next month or two. We’ve got some very cool new stuff to add, and Hobo is finally going to get the level of documentation it needs for people to really start to get to grips with it. We might even finally get some themes :-) Exciting times!

Coming up for air

Posted over 6 years back at The Hobo Blog

The big app we’ve been working on over here is finally calming down. Not finished as such, but close enough that we can start to give some attention to the hundred other things we’ve got on the go, like… Hobo!

The first benefit will be that Hobo 0.6.3 is on it’s way. There are no huge new features, but lots of little touches. In all, over 100 commits since 0.6.2. I’ve just finished the changelog (which took ages!) so hopefully this will make it out of the door tomorrow.

And of course I haven’t forgotten all the docs I’ve been promising. There’s one fairly significant change on it’s way first though - we’ve figured out a way to merge the camel-case <TemplateTags> and <normal_tags> into one kind of tag, with two different styles for calling the tag. It’s going to be a big improvement to the aesthetics of DRYML code. And while we’re on aesthetics, we’ve decided to switch from <tags_with_underscores> to <tags-with-dashes>. Don’t freak out – we’re going to provide a rake task that will update your existing DRYML source automatically. We’ve got enough DRYML code ourselves to make it well worth the effort to write that utility.

Overall you can expect to see a general upturn in activity in the Hobo project over the next month or two. We’ve got some very cool new stuff to add, and Hobo is finally going to get the level of documentation it needs for people to really start to get to grips with it. We might even finally get some themes :-) Exciting times!

I Am Not A Freeloader

Posted over 6 years back at zerosum dirt(nap) - Home

So have you heard the new Radiohead album yet? What did you think? And more importantly, what did you pay for it? ComScore estimates that 2 out of 5 of you did. They released a study today suggesting that, during the month of October, 40% of visitors were willing to pay an average of $6.00 for the digital downloads. Click that link for the full details. It’s also interesting to note that US consumers were will to pay more, on average, than the rest of the world.

The press is having a field day with this, and opinions are mixed. The ‘glass is half empty’ point of view seems to be that, holy crap, there are a lot of freeloaders on the ’net.

No kidding, really?

On the other hand, the ‘glass is half full’ folks point out that, hey, people are actually willing to pay for stuff, and that music on the ’net still has a perceived value after all.

I’m siding with the latter camp. Official sales figures won’t be released until after the holidays, but shit, I think these initial estimates are fantastic. Moreover, I think they show tremendous potential for non-compulsory tipping for digital goods in the public space. Software and media piracy is only a problem because of how we perceive and hope to profit from selling media on the web. Labels don’t need a new type of DRM, they need a new approach to what they’re selling. It’s information, and once that information is out there, it’s free, regardless of how much you perceive it’s worth to be. Magazine publishers figured this out a while back, and make their money through online advertising.

What Radiohead has done is adapt, and prove that, at least to some extent, a donation-driven model can work here. Of course, public radio beat them to the punch by at least 50 years, and they’re not the first band to sell music online, but it certainly signals a big win for those of us who believe that all web users aren’t freeloading scum. Even if the average user is a freeloader, the point is that the band can make enough from their efforts such that producing art for public consumption is profitable.

Anyway, the average worldwide price for all downloads, including freeloaders, was $2.26. I’d love to know what the bands’ actual per-album net was on their previous album, 2003’s Hail To The Thief. I’d be shocked if it was much higher than, say, $6.00 (update: this article estimates that it was probably between $3 and $5 USD). Personally I paid about $7 USD.

Oh, and the album is pretty good too.

Drop A PID For Monit

Posted over 6 years back at zerosum dirt(nap) - Home

If you ever need to drop a pid from a Ruby process it’s dead simple:

File.open('myapp.pid', 'w') { |f| f.write(Process.pid) }

Now you can use Monit to keep Sinatra alive, for instance ;-). Monit is great for monitoring UN*X processes and keeping them running under ideal conditions, and that means it’s great for Mongrel, and anything that runs through Mongrel. Monit can even check the memory consumption of your application and restart it if it seems to be leaking. Not that that ever happens, of course.

Named arguments in ruby

Posted over 6 years back at Saaien Tist

One of the main disadvantages of using ruby that I bump into is the absence of named arguments (or keyword parameters). That's no problem for methods taking just two or three arguments, but it does get confusing when you have to be able to pass more than that.

For example, the Bio::Graphics::Panel::Track::Feature#new method takes six arguments: the track it belongs to, a label, a type, the location, an array of subfeatures and a url. (Note: there's only four in the released version. Label and subfeatures are worked on at the moment...) When you get to this number of arguments, deciding what the order should be is almost more difficult than writing the actual code... You really have to start thinking about how the class will be used most often. If the user only has a track and a url, it's a bit unsightly to make him/her create a new feature by typing


my_feature = Feature.new(my_track, nil, nil, nil, [], 'http://www.google.com')

Compare that to

my_feature = Feature.new(:track => my_track, :url => 'http://www.google.com')

The way to get this to work, is to pass a hash in the method definition. There's a few gotchas, however. For instance, you can't define the defaults in the argument list directly.

The following code snippet almost works, but not quite...

class MyClass
def initialize(options = {:name => 'unknown', :size => 0})
@name = options[:name]
@size = options[:size]
end
attr_accessor :name, :size
end

But you can set the defaults like this:

class MyClass
def initialize(options = {})
@name = options[:name] || 'unknown'
@size = options[:size] || 0
end
attr_accessor :name, :size
end

In addition, you have to check if all passed keys make sense. What if a user would use the MyClass#initialize method above with a :age key? It's easy enough to catch that in your #initialize definition, but you have to remember to do that...

Another major disadvantage is the fact itself that you need a workaround in the first place. This means that it makes it a no-no if you want to integrate your classes in a bigger framework. There's no way I should use this approach for Bio::Graphics if it would be integrated with bioruby later. That would result in inconsistency in calling different classes within bioruby, which is the last thing you want...

Let's just hope ruby 2.0 will allow for using keyword parameters. (Pretty please...)

Episode 78: Generating PDF Documents

Posted over 6 years back at Railscasts

In this episode I will show you how to create PDF documents using the excellent PDF::Writer gem.

Clone Pastie in 15 Minutes with Sinatra & DataMapper

Posted over 6 years back at zerosum dirt(nap) - Home

Hey there, put on your tutorial hat. Today we’re going to learn how to write a dirt simple pastie clone using Sinatra and Datamapper. For those of you unfamiliar with pastie systems, they’re commonly used in IRC to paste bits of code to a globally-visible place outside of the channel. So you copy some code from your IDE, paste it into a web page, submit it, and the Pastie system fancies it up with some syntax highlighting or whatnot. You can then copy the resultant URL and paste it back into the channel so other people can view it.

Examples of this type of service include pastie.caboo.se and Nopaste @ rafb.net. Those sites do a lot of extra cool stuff, like allow you to select the language for different syntax highlighting, select themes for viewing, and so on. But the core concept itself isn’t a terribly complex one, and our example is going to be about as barebones as they come. The interesting thing isn’t the application we’re going to build here so much as it is the tools we’ll use. That is, we’ll be using the pastie example to introduce you to two cool new pieces of Ruby tech: Sinatra, a new web micro-framework, and the DataMapper ORM package.

Sinatra, on the surface, is a lot like Camping, another Ruby web all-in-one-file micro-framework. Camping hasn’t seen any active development in quite some time though, and the syntax can be a bit strange for new users. Sinatra is much more straight-forward and accessible. It’s really a kind of domain-specific language for writing simple web applications, used to define RESTful actions and how they should be handled. This makes it perfect for lightweight mini-apps. It’s also completely ORM-agnostic, instead of being married to ActiveRecord like both Rails and Camping are. For more information, check out the ‘official’ tutorial.

DataMapper is the new ORM package on the block, and an alternative to ActiveRecord (and Og and Sequel and so on). It just moved into town but it’s already sitting at the cool kid lunch table. Whereas AR implements the ActiveRecord Pattern, DataMapper (surprise!) implements the DataMapper pattern. There are a number of reasons why I prefer this approach, but that’s probably fodder for an entirely separate blog post, so I won’t get into that here. Besides, the team has already written a great summary of why DataMapper rocks. Read it. Oh, and performance kicks ass now too.

OK, anyway. Tutorial time. Found your plastic hat? Good. Let’s go. First let’s get the gems we’ll need. As of this writing, DM is at v0.2.3 and Sinatra is at v0.1.7. We’re also going to retrieve the Syntaxi gem, which we’ll use for syntax highlighting.

sudo gem install sinatra datamapper json syntaxi -y

Since DM uses the DataObjects.rb drivers, you’ll want to install them. They’re packaged with the distribution. For our purposes here we’re going to assume you’re on MySQL but all the standard drivers are there, so don’t fret. Change to your DM gem directory (mine is /opt/local/lib/ruby/gems/1.8/gems/datamapper-0.2.3) and issue the following command. Ignore any warnings that are generated. If you’re on OS X 10.5, you may want to check out Heimidal’s blog for instructions.

sudo rake dm:install:mysql

Now that our prerequisites are satisfied, let’s get started by creating the file toopaste.rb:

require 'rubygems'
require 'sinatra'
require 'data_mapper'
require 'syntaxi'

### SETUP

DataMapper::Database.setup({
  :adapter  => 'mysql',
  :host     => 'localhost',
  :username => 'root',
  :password => '',
  :database => 'toopaste_development'
})

### MODELS

class Snippet < DataMapper::Base
  property :body, :text
  property :created_at, :datetime
  property :updated_at, :datetime

  validates_presence_of :body
  validates_length_of :body, :minimum => 1

  Syntaxi.line_number_method = 'floating'

  def formatted_body
    html = Syntaxi.new("[code lang='ruby']#{self.body}[/code]").process
    "<div class=\"syntax syntax_ruby\">#{html}</div>"
  end
end

database.table_exists?(Snippet) or database.save(Snippet)

### CONTROLLER ACTIONS

layout 'default.erb'

# new
get '/' do
  erb :new, :layout => 'default.erb'
end

# create
post '/' do
  @snippet = Snippet.new(:body => params[:snippet_body])
  if @snippet.save
    redirect "/#{@snippet.id}"
  else
    redirect '/'
  end
end

# show
get '/:id' do
  @snippet = Snippet.find(params[:id])
  erb :show, :layout => 'default.erb'
end

Next we’ll dissect this code listing to give you a feel for how Sinatra and DataMapper work, and show the code listings for our views as we get to them.

First of all, we define our database connection for DataMapper. Looks pretty similar to its AR equivalent, eh? Before we can run this we’ll need to create the MySQL database mentioned in the source. You can create the toopaste_development database by issuing the following mysql command:

mysqladmin -u root -p create toopaste_development

We’re not going to define a migration here, as this is a very simple case, but DM does support migrations in case you’re curious. We next define our model, Snippet, which inherits from DataMapper::Base. The validators we’re specifying look familiar to anyone coming over from AR but the property declarations might look a little bit odd at first.. OMG I don’t have to put comments in my source file to remind me what attributes are available on my models?!

property :body, :text
property :created_at, :datetime
property :updated_at, :datetime

It’s like a little slice of heaven, isn’t it?

Skip over the formatted_body method for a moment and look at the line after the model class declaration that checks for pre-existence of the table. You’ll note that if it’s not found we call database.save with the model name as a parameter. This creates our table, with all the appropriate fields, as specified in the model.

database.table_exists?(Snippet) or database.save(Snippet)

The formatted_body method is simple. It just takes the body of our snippet (a property on the model) and wraps it in some code that gives us pretty syntax highlighting and line numbering. Syntaxi leverages Jamis Buck’s Syntax gem to mark up the specified code, wrapping CSS span tags around things that should be colored, adding line numbers, and some other goodies too. You’ll see the CSS in our layout shortly.

Another interesting DM optimization worth noting: by default, the text field (body) is lazily loaded. Text columns are expensive in databases, and by using lazy loading, we only access them when they’re needed. This speeds things up significantly in most cases. However, if you don’t like it, you can just pass a :lazy => false option in the text column property declaration.

Moving on to the controller actions, you’ll see that routes and actions are intimately married in Sinatra. Although this isn’t desirable for a larger application, it’s great for quickie one-off web apps like this pastie project. We only have three actions and they’re only ever available at these three URL patterns.

get '/' do
  erb :new, :layout => 'default.erb'
end

The first action displays a form to create a new paste, and it’s always available at ‘/’, your application root. Note that it’s a GET request. The body of this action renders the new.erb template, which should be in your views/ subdirectory. Instead of pulling in an external template, you could just stash your HTML inline here. This may work fine for dirt-simple applications but I prefer to keep it separate. Here’s that first view, /views/new.erb:

<div class="snippet">
  <form action="/" method="POST">
    <textarea name="snippet_body" id="snippet_body" rows="20"></textarea>
    <br/><input type="submit" value="Save"/>
  </form>
</div>

The next action is analogous to a #create action in RESTful Rails. The action is requested by a POST to the application root. Sinatra supports the standard GET and POST HTTP methods as well as PUT and DELETE, meaning that you can build RESTful applications with it.

post '/' do
  @snippet = Snippet.new(:body => params[:snippet_body])
  if @snippet.save
    redirect "/#{@snippet.id}"
  else
    redirect '/'
  end
end

Pretty standard stuff, right? We retrieve the parameter posted from the submit action in the new paste form, instantiate a new model and try to save it. If the validations pass, we redirect to the #show action equivalent. If not, we’re just going to dump you back to the #new form again. Since the only way the action will fail is if the body property is empty, we’re not going to bother with any sort of error message at this time. We’re not rendering anything here (merely redirecting), so no template is required.

If our post is successful, we’re going to be taken to the #show action, which lives at /:id, where :id is the primary key of the corresponding database record. This action will also get accessed directly when you paste that URL to the chat room, and people click to view your code.

get '/:id' do
  @snippet = Snippet.find(params[:id])
  erb :show, :layout => 'default.erb'
end

In the code listing above, we look up the particular snippet specified in params[:id] and set an instance variable. We then render an ERb template, which of course has access to that instance variable. Here’s the code you’ll want in /views/show.erb:

<div class="snippet">
  <div class="sbody" id="content"><%= @snippet.formatted_body %></div>
  <div class="sdate">Created on <%= @snippet.created_at.strftime("%B %d, %Y at %I:%M %p") %></div>
  <br/><a href="/">New Paste!</a>
</div>

If you’ve been paying attention you’ve noticed that both of our erb method calls (used to render an embedded ruby HTML view, you can also use haml) have specified a layout. That layout does the sorts of things a layout usually does; it sets up the page body, the title of the page, the styles, and so on. For completeness’ sake, we’ll list it here:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title><%= @title || 'Toopaste!' %></title>
  <style>
    html {
      background-color: #eee;
    }
    .snippet {
      margin: 5px;
    }
    .snippet textarea, .snippet .sbody {
      border: 5px dotted #eee;
      padding: 5px;
      width: 700px;
      color: #fff;
      background-color: #333;
    }
    .snippet textarea {
      padding: 20px;
    }
    .snippet input, .snippet .sdate {
      margin-top: 5px;
    }

    /* Syntax highlighting */
    #content .syntax_ruby .normal {}
    #content .syntax_ruby .comment { color: #CCC; font-style: italic; border: none; margin: none; }
    #content .syntax_ruby .keyword { color: #C60; font-weight: bold; }
    #content .syntax_ruby .method { color: #9FF; }
    #content .syntax_ruby .class { color: #074; }
    #content .syntax_ruby .module { color: #050; }
    #content .syntax_ruby .punct { color: #0D0; font-weight: bold; }
    #content .syntax_ruby .symbol { color: #099; }
    #content .syntax_ruby .string { color: #C03; }
    #content .syntax_ruby .char { color: #F07; }
    #content .syntax_ruby .ident { color: #0D0; }
    #content .syntax_ruby .constant { color: #07F; }
    #content .syntax_ruby .regex { color: #B66; }
    #content .syntax_ruby .number { color: #FF0; }
    #content .syntax_ruby .attribute { color: #7BB; }
    #content .syntax_ruby .global { color: #7FB; }
    #content .syntax_ruby .expr { color: #909; }
    #content .syntax_ruby .escape { color: #277; }
    #content .syntax {
      background-color: #333;
      padding: 2px;
      margin: 5px;
      margin-left: 1em;
      margin-bottom: 1em;
    }
    #content .syntax .line_number {
      text-align: right;
      font-family: monospace;
      padding-right: 1em;
      color: #999;
    }
  </style>
</head>
<body>
  <%= yield %>
</body>
</html>

Save that listing as views/default.erb. The rendered page content will be inserted into this layout where it yields. And that’s pretty much it. You can fire up your new Sinatra and DataMapper-powered application by issuing the following command:

ruby toopaste.rb
== Sinatra has taken the stage on port 4567!

Sinatra sits on top of Mongrel, making it super-easy to use (and thread-safe to boot!). If you open up a web browser and point it at http://localhost:4567 you’ll see the results. You now have a fully functional (albeit slightly retarded) pastie clone with syntax highlighting for Ruby code snippets. And the core logic is all contained in a single file, with a few external ERb templates for cleanliness.

If you like, you can play with the finished app or download the sources. Enjoy, and please comment if you have any problems or suggestions for improvement. This code was written and tested on OS X 10.4 and Debian Etch.

UPDATED 07/02/08: I finally got around to updating this tutorial for DataMapper 0.9.2. About time, eh? Click here to see the new version.

Addressable Now One Point Oh

Posted over 6 years back at Sporkmonger

I just released version 1.0.0 of my Addressable library. The most useful change is the addition of a new heuristic parsing method, similar to how most browsers handle URIs entered through their address bars. Passing “example.com” to the heuristic_parse method will end up returning a URI that is equivalent to “http://example.com”. The URI can then be further normalized as necessary.

In addition, there are several minor changes that might cause compatibility issues (although probably not). The path component of a URI is now guaranteed to never equal nil. The code in the parse method for handling the feed pseudo-protocol has been removed and placed within the heuristic_parse method where it belonged in the first place. The to_h method has been renamed to to_hash so that coercion will work. There were also a couple of small bug fixes, mostly related to routing.

All of that stuff is great of course, but the main reason I’m slapping the “One Point Oh” sticker on this thing and calling it “done” is that now, in addition to having 100% code coverage, Addressable can now manage to go through the heckling process with no surviving code mutations. That’s a pretty high bar to get over, so I think it’s fair to call this thing finished.

The November Hackfest is upon us!

Posted over 6 years back at Weblog - Home

No sooner has one Hackfest finished another one kicks off. We have a fantastic top prize this month courtesy of Oakley. Just take a look at these:

Oakley O ROKR PRO

Prize details:

"Cut the cords and push your training session to the next level with wireless audio freedom. O ROKR™ Pro is Bluetooth Stereo eyewear that unleashes your potential. You no longer have to be tethered to your mobile phone or favorite MP3 Player, they can be safely stored away in a backpack or pocket. With a secure fit and an advanced sweat-resistant design, it’s an incredible training tool. Listen to music and make calls virtually anywhere with a system that adjusts easily for when you need to hear your environment. Cut the cords and take advantage of the razor sharp clarity of High Definition Optics® (HDO®)."

It is possible to cram any more technology in a pair of sunglasses? A very cool prize for a lucky winner. On a side note, Oakley are looking for a Rails developer. Perhaps that could be you?

Not to be forgotten O'Reilly continue to support the contest with a top notch supply of books and magazines for the runner-ups.

Good luck everyone!

Javascript + embedded Ruby templates with Rails, out-of-the-box

Posted over 6 years back at mad.ly

I recently tried using Dan Webb’s MinusMOR plugin, which allows you to write Javascript templates with embedded Ruby (a la .html.erb/.rhtml templates), but I was disappointed to find out it didn’t work with Edge Rails. I found a random Pastie via Google that seemed to fix the plugin for Edge, and this worked okay, with the [...]

October Hackfest Winners Announced

Posted over 6 years back at Weblog - Home

A big thanks to all the contributors who took part in the October 2007 Hackfest.

The results are now out:

October Hackfest Winners

Well done to Lawrence Pit who landed the top spot and a fantastic prize of a Ruby on Rails Boxcar hosting solution from Planet Argon

Boxcar

The runners up get a variety of books and magazines thanks to O'Reilly. Congrats!

Hackfest Winner Interview: Pratik Naik

Posted over 6 years back at Weblog - Home

Pratik Naik is a long-standing Rails contributor. He has won the Hackfest on multiple occasions.

Originally from India he currently lives and works in London and is a regular attendee to the Ruby users group in the city.

Pratik is also best known in the community for creating the popular Rails blog aggregation site Planet Ruby on Rails

Q: What is your connection to Ruby on Rails?

I started my career with Oracle India, and spent almost 2 years there working on several customer facing internal web apps using perl/mod_perl. And 2 years on perl were enough to build a love/hate relationship, so while looking at new technologies/solutions I came across ruby/rails and fell in love with it instantly. And now I've been working professionally with Rails for almost a year and half.

Q: Tell us about the sort of contribution you made during the contest.

Apart from minor ActiveRecord/ActionPack fixes and pluginizing some functionalities, my major patches were for refactoring of render methods and association callbacks.

Q: How did you first get involved contributing to the Rails source?

In the past, I had made some contributions to mod_perl project. And I first got involved contributing to rails in a very short time after starting to work on edge rails. Contributing to rails is a lot easier than people ( mainly those who are new to rails ) usually think. Everything in rails is pure ruby after all. #rails-contrib irc channel is probably the best ( and fastest ) way to get core related help and finding people to review your patch.

Q: Tell us about your development environment

Mac and big screens.

Q: Rails 2.0 and beyond - where next?

I think the next steps would be to work towards making rails thread-safe and cleaning up some fugly code. And also have rails run smoothly on next major stable ruby release in 1.9 series, as it has major performance enhancements over 1.8.x.

Q: Closing words

I've been meaning to bring back to life my first rails project - FreeOnRails, which is hibernating at the moment due to my time crunches. It's a project for providing quality free rails hosting to those in need. Interested people can join the mailing list where I'd be posting all the further updates.

Apart from that, you can usually catch me in #rails-contrib and #rubyonrails irc channels (nick : lifofifo) or lrug meets. I also try to blog regularly at http://m.onkey.org

Gotta love *those* recruiters

Posted over 6 years back at work.rowanhick.com

From a blanket spam email I (and probably a good portion of the rails community just received) "I have a direct client who is seeking a strong Programmer who posses experience with Rudy on Rails. If you are qualified and interested, please send me your most current resume in a word.doc format to.." Yes, Rudy was actually put in bold, just to place even more emphasis on the spelling error.

Blog Updates

Posted over 6 years back at zerosum dirt(nap) - Home

So I finally got around to migrating the blog site over to Mephisto. I’ve only been planning on doing that for like 9 months. Horray for progress!