For many months when git (or really when github) first arrived on the scene I heard nothing else from all the fanboys than how great git was, how crap svn was, and that everyone who was anyone was using git now. That sort of zealous response to new software or services always gives me pause.
Inevitably, I’d ask one of the fanboys why they recommended git over svn, and usually they would come up with one of two standard “reasons”
This is a small thing, but sometimes those small things can really make a huge difference. This is one of those.
As your suite of tests grow, especially in those large applications, you often end up with an error output that looks something like this:
..........F..............F.....E....FFF...F..........
And then following that is a huge list of error details. Scrolling through that is a pain, and even with redgreen active your visual cues are at a minimum when looking through that output.
Thankfully this also annoyed Tim Pease who came up with a very pleasant alternative called turn. You can install it as a gem, and then just add:
require 'turn'
Into your test helper and you’ll see much simpler and comprehensible output from your test output.
Almost immediately after posting my last post on the Rails console a few more things came to mind. It has taken me this long to blog again :)
Let’s pick up from where we left off in the previous post with…
So, those of you that know me know that I’m no REST zealot. I think there are many times when it’s better to use a non-REST controller. Simplicity of URLs, succinctness of controller, etc..
One example that I’ve just come across is a questionnaire which doesn’t really map to REST. For a start I never want to expose this controller via an API, the process flow also doesn’t follow REST at all, sure I want a new questionnaire completed, but that’s it. I don’t want to be able to show, edit/update or delete.
I spent a little time this week pulling sorting out of a project of mine as a gem. I’m really happy with where I got to with it.
What this is is something that lets you very easily add column sorting to your data views so that visitors can click on the column headings to re-present the data sorted by that heading.
So for anyone who doesn’t know, the script/console in Rails runs up an irb process behind the scenes. It also loads Rails into the context, and a few other bits - but mainly it’s an irb session.
I’ve just been getting a couple of “Oh wow, I didn’t know that.” responses when I mention these things in #rubyonrails, so I thought I’d just post this here.
Thing 1: the underscore method
The return from every command that you enter into irb is available in the underscore method _. So, if you’re like me, you often run a command and then think that you should have assigned it to some variable, or pretty-printed it or something.
One of the things that quickly tripped me up in using SQLite in Rails was that there was no way to make a column case insensitive.
Most human textual comparisons are case insensitive, we think that “dog” and “doG” and “DOG” all denote the same thing. If we have a uniqueness constraint on a column, then we want it to protect us from having three separate entries for those three strings. Also, when we’re searching for “dOg” we want it to match any one of the three strings.
Every database has its own way of doing these sorts of things - SQLite uses one of the more sensible methods: it allows you to specify that any column you like should be case insensitive (and then any index on that column will automatically be case insensitive too).
So, you can write:
CREATE TABLE foo ( bar varchar(255) COLLATE NOCASE );
And you’ll get a case insensitive column ‘bar’. This is so often what you want, more often than not, so I wrote a quick gem that does this by default for all your migrations.
This is a kludgy kludge!
What would be nice would be to add a new option to the migration methods so that any given column could be marked with something like: :case => false Unfortunately, the Rails code for all that is not very DRY and stuffed with metaprogramming - so it’s not easy to retrofit a gem to make that happen. So my gem just makes it happen for every string or text field.
Mostly this will be what you want, but every so often case sensitivity is something that is desirable - so beware :)
Ok, so there are chunks of code I write again and again, and this is one of them:
class Version
include Comparable
def initialize(_v); @v = _v.split('.').map(&:to_i); end
def <=>(_v); @v <=> _v.split('.').map(&:to_i); end
def to_s; @v.join('.'); end
end
I was going to reformat it, so that the methods are all newlined properly, but actually - you should have to put up with looking at it like I look at it.
So, what does this do? Well, check this irb out:
irb(main):001:0> '3.6.8' > '3.6.4'
=> true
irb(main):002:0> '3.6.8' > '3.6.10'
=> true
irb(main):003:0> # Ack! Should be false
We get a true because they’re strings, so they’re being compared alphabetically. Rescue us wonderful Version class:
irb(main):004:0* class Version
irb(main):005:1> include Comparable
irb(main):006:1> def initialize(_v); @v = _v.split('.').map(&:to_i); end
irb(main):007:1> def <=>(_v); @v <=> _v.split('.').map(&:to_i); end
irb(main):008:1> def to_s; @v.join('.'); end
irb(main):009:1> end
=> nil
irb(main):010:0> v = Version.new('3.6.8')
=> #<Version:0x547e0 @v=[3, 6, 8]>
irb(main):011:0> v > '3.6.4'
=> true
irb(main):012:0> v > '3.6.10'
=> false
Yay. That’s it, you can get it here.
Let’s get into it. SQLite kicks arse! It wipes the floor with MySQL and comes back for more. The only time not to use SQLite is when your app goes viral and you have six or seven figure hits per day at which point you should go to Postgres.
Where does MySQL fit in? Nowhere!
What are DDLs and what does it mean to have Transactional DDLs?
Why does SQLite rule, and why would I consider it for production?
What does “lite” really mean?
Read on…
New look and feel - I quickly ported Scribbish over to simplelog because I was sick of the dark. Next I want to find out whether I can easily get syntax highlighting onto my webhost.
Stay tuned for posts about transactional DDLs coming soon for SQLite in Rails 2.3.
Also a really neat tool for getting started on a new gem.
Also a really nice tool for viewing your test output and making it a bit clearer (especially good for those huge test suites.
Back soon.
Oh, I just stuck it up on GitHub, here.
As I pointed out here on the WWR Forums when you have a set of static conditions, even if you only use them once, then you should consider using a named_scope to encapsulate those conditions in your model.
So instead of having this in your controller:
app/controller/foos_controller.rb
def inactive
@foos = Foo.all(:conditions => "active is null")
end
You would shift that concept off into your model by using a named scope. So you’d have this instead:
app/models/foo.rb
named_scope :inactive, :conditions => "active is null"
app/controller/foos_controller.rb
def inactive
@foos = Foo.inactive
end
Note that what’s returned from inactive is a proper ActiveRecord collection, so you can call all your AR records on it, eg:
@foos = Foo.inactive.find_all_by_bar(params[:bar])
This is a great way to push the business logic off into your model and refer to it by name (not code) from your controller.
A/B testing, split testing, side-by-side testing, call it what you like but for those interested in improving the performance of their marketing it’s crucial to test your copy, headlines, imagery and visual arrangement.
I’ve just packaed up guerrilla_rotate, an internal tool that I’ve been using for a while, and stuck it up on my new best friend: github
It’s best to use this in combination with Rubaidh::GoogleAnalytics in which case it’ll just do what you expect for your stats. If you don’t use that, then you’re on your own with how to track the stats, manual analytics of some sort, or who knows - old school, unique image tags in each view.
Have fun.
I’ve just rewritten inline_attachment to have more features, with less code, and be more reliable (ie. not as likely to break with a Rails version bump).
The coolest new feature is full support for the ActionMailer auto-multipart feature, so mostly you won’t need to write any complex MIME part crap in your model. No code is always good :)
Quickly
app/models/notifier.rb
class Notifier < ActionMailer::Base
def signup
recipients %q{"Testing IA" <testing@handle.it>}
from %q{"Mr Tester" <tester@handle.it>}
subject "Here's a funky test"
end
end
# Oh yeah baby! Read it and weep! So how's this work? Well, you'll need
# your templates named properly - see the `Multipart email` section of the
# ActionMailer::Base docs.
signup.text.plain.erb
Your username is: <%= @username %>
signup.text.html.erb
<html>
<head>
<title>Signup Notification</title>
</head>
<body>
<%= image_tag "logo.png" %>
<p>Your username is: <%=h @username %>
</body>
</html>
Obviously you also need that logo.png in your public/images directory.
Someone on #rubyonrails asked a question the other day, whether there was a capistrano task to open a script/console over ssh on the remote server. Such a brilliant idea that I asked him to fill me in if he found it - and he did, here
Instead of having to open an ssh session, and cd to the right dir, and fire up script/console you can just use the cap task from the comfort of your project dir on your local machine:
cap remote:console
I’ve ditched this because to_param is just such a simple solution. Google it and read, it’s so simple.
When we incorporated Google Adsense into Freedraw we just couldn’t find a simple to use plugin that would insert the ads we needed into our layouts.
How the plugin works is simple, you define how the ad should look within your config/googlead_sense.yml file (a sample one is provided with the plugin). You’ll want to change at least the adclient setting otherwise I’ll get all your ad revenue.
Actually, don’t change that setting! :)
Then just add it into your views or layouts, like so:
<%= google_ad %>
This is a bit different to how the old one worked, you used to have to define all those settings in each controller that you wanted to use the helper in.
This is simpler, and you still have some control over the format in your view, like so:
<%= google_ad(:skyscraper) %>
To install the plugin:
script/plugin install git://github.com/JasonKing/google_ad_sense.git
You can see more here
For those you who are unfamiliar with our new approach to user authentication click here to read all about it.
We’ve finally completed a plugin for those who want to try out this new password-less method of user authentication.
The plugin is based off of the well known Restful Authentication plugin so it should be fairly straight forward to use and integrate with your own systems.
I’m rewriting and rethinking this plugin (really a generator), and how it can best be integrated into really useful things like IM and maybe twitter.
Something which I’ve really fallen in love with recently is something I’ve named Just-in-Time Branching. It allows my coding brain to just code without having to think about whether something is so large that it has to be branched, and I don’t need to think about when the next release is going to go out, or what the other developers and doing and whether what I’m doing will interfere with their code.
You heard it here first (except for here, and hijacking attempts here and here) - the acronym of the moment is SNAP: Social Networking APplication. Be an early adopter! Stop writing it out longhand and join all the k00l kidz (actually I’ll settle for just having a blog article to point people to when they ask me what I mean when I use SNAP.
Something which I came up against fairly early on in my Capistrano use was the problem of releasing from tags or branches in SVN. My normal development process for a large release is to tag the trunk, and then release from the tag. Then there are other times when I have a long-running branch that I want released as well. These posed some problems for Capistrano because the repository location was baked right into the deployment scripts.

