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_nameSELECT * 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_nameSELECT * 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
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
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
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.
