Articles about BiQ on Rails

On Rails 2.0, SQL Server adapter, gems, vendor and load paths

Over the last few days I have been moving the BiQ application to Rails 2.0 PR. I’ve so far run into a fair deal of issues; one annoying one that I figured I’d share.

The gist of the matter is that creating some of my models failed in some cases. It appeared to be primarily when the save triggered an insert into another table as well.

Digging around a bit, I traced it down to the fact that the newly created model was given an id that didn’t match the id in the database. The reason for that turned out to be quite the sneaky little bastard…

BiQ is hiring

Update: This position has been filled. Thanks a lot to all of you who applied.

Do you want to do Ruby for a living, and are you located in Copenhagen (or willing to travel/relocate)? We’re looking a for a solid developer who can do a bit of all things web, who isn’t afraid of neither Windows nor Linux, and who wants to make a difference for one of Denmarks first public facing Rails applications.

Official position description (in danish) is over here.

You’ll be part of a small team and you’ll be working closely with me (gee, what else can you ask for? :P). I am probably biased, but I find BiQ to be a great place to work – I probably wouldn’t have lasted 6 years in this position otherwise.

Anyways, get in touch with me or my boss if you’re interested in hearing more.

Warning: GZip content, Flash Player, and Internet Explorer 6

This is a followup to my post about using YSlow to optimize websites with a warning.

In that post I mention using mod_deflate to GZip encode all our text based content before delivering it to user agents supporting this. However, I’ve hit an issue with a specific browser. Yup, you guessed it, off course Internet Explorer doesn’t behave properly.

It seems there is an issue when Flash Player 9 running in Internet Explorer receives GZip-encoded content from the server. While IE has no problem with GZipped content on it’s own, it apparently fails to unpack and deliver the content to the Flash player.

This took our network mapper offline until we were alerted to the issue. This means we have to remove GZip encoding for all the content that the Flash player requests. Unfortunately I have not been able to find an easy way to do this just for the Flash player, so I’ve opted for turning off GZip encoding for all the requests to network.xml:

SetEnvIf Request_URI "/network\.xml" no-gzip

Sigh, why can’t things just work out of the box in this business.

Using YSlow to optimize websites

Yahoo! has released a great Firefox addon – or rather, an addon for a Firefox addon – called YSlow. YSlow allows you to analyze and suggest improvements to various performance metrics on the website you’re currently visiting.

For kicks I decided to let it loose on biq.dk. Unfortunately it gave me a disheartening grade of F:

Performance grade: F (46)

Ah well, sounds like a perfect opportunity to improve, and the rest of this entry contains the areas where the biq.dk frontpage did not receive an A-grade, and a description of the modifications I had to perform on our setup to satisfy the addon.

Prototype and TEXTware QUICKfind vs Internet Explorer

You know we’re sitting on four million pounds of fuel, one nuclear weapon and a thing that has 270,000 moving parts built by the lowest bidder. Makes you feel good, doesn’t it?

After launching the rewritten and redesigned BiQ I got word of seemingly random IE installations crashing within seconds of opening BiQ. I could not find a way to reproduce this and it only occured on a tiny minority of client installations, so I shrugged it off as yet another reason to upgrade to Firefox.

Launch: BiQ on Rails

After 6 months of evangelizing and advocating, followed by 6 more months of rewriting, and then 3 more months of building new features and enhancing existing ones, we have finally launched the new version of BiQ.

Going from ASP/VBScript on Windows 2000 and IIS to Ruby and Rails on Debian served with love by Apache proxy balancing to a Mongrel backend, using memcached for relieving the database of those common queries, with continuous integration provided by Cruise Control and easy deployment through Capistrano sure as heck feels good.

Add to that the fact that the new look is quite delicious and powered by standards compliant XHTML sprinkled with a tiny amount of Ajax and a hint of microformats and Atom feeds, and has a blog and some new killer features and you’ll probably understand why I am happy.

Now it is time to make the site even better. ;)

2006 in retrospect

It’s a new year, and of course, this calls for looking back at the year that passed. The short version: 2006 has been a great year for me on several levels.

Professionally

Career wise 2006 has been coloured primarily by Ruby on Rails.

I founded my freelance web application development shop in January and started having fun building Rails stuff for clients (with the launches of Pluggd and MedBillManager being the highlights).

On the day job, my boss finally caved in after hearing me evangelize and rave about Ruby, and in March we started looking at the possibility of Rails as our new platform.

The final decision, which was luckily a go, came in July and the actual rewrite began making my dayjob ever so more interesting.

On the more social side of Ruby and Rails, 2006 also became the birth year of the Copenhagen Ruby Brigade. By now we hold (almost) montly meetings usually with around 20 smart and fun participants, healthy discussions and unhealthy fast food.

Virtually

The life of mentalized has been a exciting ride throughout 2006 as well.

The year was kickstarted when my satirical Building your very own web2.0 layout reached the Digg hordes in February and became the most visited page on mentalized in 2006 with 175K pageviews.

The runner ups in the category “top content of 2006” are my free AJAX progress indicator images with 107K pageviews. These are still going strong and getting a fair amount of hits every day.

Honorable mentions go to some of my Rails related tutorials: No such file to load — mkmf and Putting Debian on Ruby rails.

It looks like the advice I can take away from 2006 is that writing jokes, giving stuff away for free, and posting images of scantily clad women are great ways to increase your pageview statistics…

One reason to upgrade Ruby to 1.8.5

Last week I took a quick executive decision to deploy BiQ on Debian Etch instead of Sarge as initially planned. Mainly so we could take advantage of Ruby 1.8.5 (let me hear you scream “Mongrel”) and Subversion 1.4.something.

Today, yet another reason for going with Etch just bit me in the behind while using our development machine:

What's going on around here

It’s been pretty quiet around these parts lately – if you ignore the posts about Copenhagen.rb meetings at least. That’s primarily because I am having tons of fun at work, which for some reason doesn’t leave me much time for blogging. Not that I would ever think of blogging at work, no siree…

Anyways, here are some tidbits about what’s be going around my life recently:

  • The BiQ rewrite is going really well, and I am thoroughly enjoying this.
  • Copenhagen Ruby Brigade has taken off and the two meetings so far have been visited by 20-25 Ruby heads. I’m really enjoying these meetings and the more social side of software.
  • My girlfriend started blogging – primarily for a school project, but it will be interesting to see if she keeps blogging.
  • Substance Lab is busy with client work.
  • The puppy is growing bigger – she’s almost a real dog now.

acts_as_legacy

At the recent Canada on Rails conference Robby Russel introduced his upcoming plugin, Acts as legacy. Facing a 60+ table legacy system, I will definitely be watching that space. Acts_as_legacy would allow me to not worry about our existing scripts and jobs, while still rolling BiQ onto the rails.

For now, though, I am still partial to the idea of changing my tables around. Mainly to spare my poor fingers from having to type out stuff like intRelationValueRelation when building queries. relation_id makes so much more sense.

Decisions decisions.

Using SQL Server views as Rails "tables"

In an effort to get a feel for the effort it’ll take to rewrite BiQ, I’ve been rewriting a vertical slice of our functionality. As part of that I’ve been setting up a test Ruby on Rails application and building a test suite for it.

One pretty important piece of the puzzle is our database. Over the years it has changed from the realm of an application database into being an integration database. Part of the rewrite is my desire to revert that.

I really want to change our database structure around so it matches the conventions of Rails. I believe the cost of doing so is by far outweighed by the benefits, especially since I’d have to map everything to some other name in our models otherwise.

tblUser.strUserFirstname is probably one of the worst naming schemes I’ve ever come up with. Having to create attribute accessors for everything isn’t going to make me like it a single bit more.

For now, while we’re exploring and testing, it will probably be most beneficial to preserve the old naming scheme. That way we can run tests and compare results on both the ASP/VBScript and the Rails application. Also we have scripts and stored procedures outside the ASP/VBScript application expecting the old structure that won’t be part of the initial rewrite.

SQL Server saves

My initial idea was to create simple views that create a 1-1 mapping of each table, renaming the columns as I see ie:

CREATE VIEW users AS SELECT intUserId AS id FROM tblUser).

This idea is great in all it’s simplicity because SQL Server makes this kind of views updatable. “Jakob”, I thought to myself, “you’re a genious”. Then I ran my tests and errors were everywhere.

ActiveRecord objects to my idea

For test fixtures to work in a predictable way you need to be able to insert into their id columns. To enable that on a table in SQL Server you do set identity_insert tableName on. However, Rails expects my table to be named users, but the database object by that name is really a view, hence I get the error:

ActiveRecord::ActiveRecordError: IDENTITY_INSERT could not be turned ON

Which in reality masks this error:

‘users’ is not a user table. Cannot perform SET operation.

Bummer. It was a good idea, though.

Create a trigger on the view to turn identity insert on

Creating an Instead-Of-Trigger that turns identity insert on is a fairly clean solution. It doesn’t work, though. The SQL Adapter always check if the insertion has an id column and if it has tries to turn identity insertion on. This results in the above error, since it uses the view name.

Hacking Fixtures

The above behaviour turned me onto something, though. There is a single method that handles turning identity insertion on and off: ActiveRecord::ConnectionAdapters::SQLServerAdapter.enable_identity_insert. Bingo! There’s my attack vector. I added the following ugly-as-heck-hack to test/test_helper and everything works:

module ActiveRecord
  module ConnectionAdapters
    class SQLServerAdapter < AbstractAdapter
      def enable_identity_insert(table_name, enable = true)
        if has_identity_column(table_name)
          "SET IDENTITY_INSERT tbl#{table_name.singularize} #{enable ? 'ON' : 'OFF'}"
        end
      end
    end
  end
end

At least our current database conventions are consistent enough for the above to work. I should probably reconsider my choice of not wanting to change the tables around, but this hack will serve me well until we move ahead with the actual rewrite.