Rotator.js

For some work we’ve been doing for Halogen Guides I needed to rotate some content in a div. It needed to look slick, be easy to write, and simple to use so I settled on JavaScript using the Prototype and Scriptaculous libraries.

It’s quite simple to use:

Syntax


new Rotator('id_of_element', [options]);

Options

Option Default Description
tag “div” A string with the tag used for the rotating elements.
className null An optional string for further limiting rotating elements by their class name.
frequency 5 The frequency in seconds at which the elements rotate.

Download – Rotator.js

named_scope and includes

I’m in the process of converting one of my apps from using scope_out (pre Rails 2.1) to named_scope. One of the big benefits I found of using scope_out was that I could handle eager loading and ordering, sometimes skipping any filtering altogether. For instance, in the Halogen Aircraft Marketplace I wanted to grab a list of seller profiles with their associated users and sort them by company_name (if they had one) and the user’s name. With scope_out this was:

1
2
3
4
5
6
7
class Seller < ActiveRecord::Base
  belongs_to :user

  scope_out :list, :include => :user, :conditions => "1", 
    :order => "sellers.type, sellers.company_name, " + 
              "users.first_name, users.last_name"
end

As you can see, the conditions clause is just a dummy that’s always true.

While this worked fine in Rails 2.0, the trouble came when I upgraded to 2.1. Both scope_out and named_scope failed to work, giving me the following SQL error:

Mysql::Error: #42S22Unknown column 'users.first_name' in 'order clause': SELECT * FROM `sellers` ORDER BY sellers.type, sellers.company_name, users.first_name, users.last_name

The fact that both failed leads me to believe that there was an underlying change in with_scope, though I didn’t have time to verify this. I just wanted to get named_scope working properly.

The issue I discovered, was that the :include portion of the clause was grouped into a separate query after the initial one, like such:

SELECT * FROM `sellers` ORDER BY sellers.type, sellers.company_name, users.first_name, users.last_name
SELECT * FROM `users` WHERE (`users`.id IN ('1','2','3'))

Well this was no good, I wanted to access users in the first query so I could do my sorting. The trick I discovered is to add an additional join clause like such:

1
2
3
4
named_scope :for_select, :select => "sellers.*", :joins => :user, 
  :include => :user, 
  :order => "sellers.type, sellers.company_name, " + 
            "users.first_name, users.last_name"

This generates the following SQL:

SELECT sellers.* FROM `sellers` INNER JOIN `users` ON `users`.id = `sellers`.user_id WHERE (1) ORDER BY sellers.type, sellers.company_name, users.first_name, users.last_name
SELECT * FROM `users` WHERE (`users`.id IN ('1','2','3'))

UPDATE: If you use this method, you’ll also need to add a :select option to make sure that variables from the joined table don’t overwrite the original.
UPDATE 2: The dummy conditions clause wasn’t necessary for named_scope. It’s been removed.
UPDATE 3: This fix does still retain a sort of hack status as calculations will not work with this named_scope. I suspect that there may be a bug in the way named_scope is processed that, if fixed, would make this hack unnecessary in the first place.

Since users is now joined in the first clause sorting works properly again. I know this is not as DRY as we would like, but until someone finds a better solution, it works for me.

Halogen Guides Aircraft Marketplace

The Halogen Guides Aircraft Marketplace is up and running. After a few months of iterative development, I'd like to believe that we have built a competitive marketplace for jets. HalogenGuides should be able to take this and blow the doors off of the competition. There's optimization and tweaking remaining, but we have a 1.0, and that's stable, mature, and usable.

ActiveRecord::Tableless

So it seems I’m diving into github pretty quickly here as I now have another project. Well, more accurately, it’s not my project but a fork off of a Kenneth Kalmer’s ActiveRecord::Tableless which you can learn a bit about on github. There’s more information his site but it appears to be having some issues at the moment.

Anyway, it’s a really simple gem for setting up tableless ActiveRecord models. You get nice things like typecasting and validation for models that you don’t want to save to your database. I’m using it for building searches but it also works well for email forms and the like. I’m not sure how much more complicated it can get, but I’m looking forward to seeing what Kenneth and anyone else will do with it.

ActiveRecord::MTI

For a project I’m working on I found myself really wanting Multi Table Inheritance (or Class Table Inheritance, as it is also known). ActiveRecord has a great Single Table Inheritance (STI) mechanism but my subclasses were going to have more distinct fields than I felt comfortable putting in one table. I could have made them distinct models but they had enough functionality in common that I it still made sense to have them as subclasses.

I know other MTI solutions exist for Rails but they either did not implement it natively (at least one used a polymorphic based hack), or they had so little documentation that I didn’t really know what to do with them.

So, with these things in mind, I set out to roll my own plugin*. Since I’m not feeling very creative it’s called ActiveRecord::MTI (for the moment at least). You can check it out over on github if you’re interested. It still is not fully finished and has a few quirks but it does what I need. I gave it some half-decent documentation so it’s possibly that you’ll be able to figure out how to use it on your own. If not, I hope to post some more detailed information on it soon.

*Yes, I know it should be a gem, but I haven’t had a chance to get around to that yet.

Highwinds

For nearly a decade, I've known Craig Nealy, from Critical Path, to Limelight Networks, Vitalstream (acquired by Internap), and now Highwinds. He's an incredible salesman and a phenomenal guy, bringing success with him as he goes. If a fraction of his skills rub off on me, I'm in great shape.

I'm proud to be working with Craig again, as the ink dries on our reseller contract with Highwinds. This opens up a new product line for us, content delivery networks, allowing us to work more deeply in the video space. While it's a bit sparse, we'll be adding significantly to our Highwinds site. If you're getting into video, or need to distribute large amounts of data, drop us a line!

Halogen Guides

We've recently re-engaged Halogen Guides, formerly known as Helium Report, on a new, under wraps, Ruby on Rails project. They target high net-worth individuals, a new market for i5 (and one I wouldn't mind being a part of). We're working closely together on both the design and development of the project, and with frequent iterations and lots of customer feedback. Version 1.1 gets iPhone compatibility!

RSpec, Helpers, and Render

Today I was being a good coder and was writing some RSpec tests for a large Rails app I’m working on. In one of my helpers I render a partial. When I ran the test I encountered this not so nice error:

1
2
<NoMethodError: undefined method `render' for 
#<Spec::Rails::Example::HelperExampleGroup::Subclass_1:0x32178f4>>

So I assumed that I had to stub render:


SomeHelper.stub!(:render)

Hmm… no luck there.

What about?


Spec::Rails::Example::HelperExampleGroup.stub!(:render)

Not that either.

Turns out the solution is stupidly simple. Just stub it right where it is. Don’t I feel smart now…


stub!(:render)

Maybe that’ll save one of you a few minutes.

Welcome

So somehow you stumbled across our blog even though we haven't yet announced it. How? We're not sure how but we're guessing that, wishing to glean what knowledge you could from our vast store, you thought to look for a blog where our wisdom would flow. Hoping against hope you typed "blog.i5labs.com" in your location bar and were greeted with this page. If that was indeed your wish you will be sorely disappointed as this is all we have here. But do not fret, we hope to have more substantial material for you in the near future. - The Staff