Another day, another release: updated calendar_helper

I’ve just had my first patch accepted on an open source project. Quite chuffed with that! As of this weekend, the Rails calendar_helper plugin is now at version 0.21. My changes are very minimal, and only really to do with the markup.

Firstly, the default table markup’s had an overhaul. The date now goes into a %lt;caption> tag, outside the <thead>, as is appropriate. The <th>’s in the thead now have scope="col" applied to them, again, as is appropriate.

The only other change is optional. If you pass in an option of :accessible => true, any dates in the grid which fall outside the current month will have <span> class="hidden"> monthName</span> appended to them. It could be reasonably inferred that plain numbers are dates that relate to the caption of the table, but the numbers outside the current month should probably be clarified.

You can come up with your own method of hiding content marked as .hidden; at NPG, we use the following:

.hidden {
	position:absolute;
 	left:0px;
 	top:-500px;
 	width:1px;
 	height:1px;
 	overflow:hidden;
}

but really, use whatever you’re most comfortable with.

You can get the plugin from Geoffrey Grosenbach’s subversion:

http://topfunky.net/svn/plugins/calendar_helper/

via the usual Rails plugin installation method.

26
April
2007

Textmate command of the day: (slightly) better Ruby test definition

As a Rubyist and Textmate user, you’ll probably be aware that def will tab-expand to stub out a method definition. You might also be aware that, for the purposes of Test::Unit, deft will tab-expand to a test method beginning def test_, allowing you to append the name of your test.

But that’s not much more help, because if we’re naming our tests properly, they’re probably going to have very_long_names, and hitting underscore all those times is a bit of a pain. So I rectified that, with this command (and it’s a command, rather than a snippet, because of all the processing it does). Pull up the commands dialog (Command-Opt-Control-C), create a new command in the Ruby bundle, and give it the following code:

#!/usr/bin/env ruby

name = STDIN.read.strip
testname = name.gsub(" ", "_").downcase
print <<OUTPUT
	def test_#{testname}
		\$0
	end
OUTPUT

The command’s Input should be “Selected Text” or “Line”; its Output should be “Insert as Snippet”. The scope should be set to source.ruby. And give it whatever key definition you want; I’ve got it on ctrl-opt-shift-t.

Usage is easy. On a new line in your test file, type the name of your test in plain English with no punctuation, eg:

get to index should list all items

and then hit your shortcut. You’ll get the following out:

def test_get_to_index_should_list_all_items

end

and your cursor will be slap bang in the middle of the test, indented, ready to write. That’s what I really want from a test definition snippet - something more than deft supplies. It’s another minute or two’s work to make it strip punctuation, so you can convert real sentences to test cases. I just decided to condition myself to save on coding on this morning’s commute.

03
April
2007

code

Tagged as:
, , .

Rails mistake of the day: validating a relationship before it’s created

(I wasted about half an hour on this last night, and am now kicking myself about how simple it was. Given that… definitely worth documenting the problem, so that no-one else gets held up on it.)

I’m currently working on some forum software (before you yawn: it’s not your average forum, it’s not worth the effort forking Beast, and besides, it’s a learning exercise). In this forum, when you create a topic, you also create the first post in the topic at the same time. Here’s how that happens (I don’t think I need to show the form view - the controller will suffice):

@topic = Topic.new params[:topic].merge(:user => current_user,
                                :forum => Forum.find(params[:id]))

post = @topic.posts.build(params[:post].merge(:user => current_user))

Unfortunately, I was running into all sorts of problems - in that even though the forms were filled out and being passed to the controller, the topic wasn’t being created. This was because the post wasn’t validating. Turns out the problem was that in my post.rb, I’d said that a Post validates_presence_of :topic_id. This validation was clearly being run before the topic was created; given we’re using build to make sure the post is attached to the topic, I don’t think we need that validation. Once I stripped that out, everything worked fine.

A pretty trivial error, I know, but once my tests started failing, I had to take the application apart a little to find out what was going on. In a nutshell: I don’t think you always need to validate relationships that have to exist for the model to make any sense.

Of course, if there’s a way I can keep the validation of topic present but still build the topic/post combination as above… comments are very welcome.

13
January
2007

code

Tagged as:
, , , , .

0 errors, 0 failures

I wrote my first proper Unit Tests in Ruby today. It felt good.

That probably sounds slightly gauche and hypocritical coming from a Rails developer. But remember - I’ve come from a front-end background; most of the time, other people make the tests; it’s up to me not to break them. I’m perfectly capable of editing tests to bring them in line with updated functionality; it just tends to have been the case that I’ve never really got my head around testing properly.

That changed recently, mainly thanks to Geoffrey Grosenbach’s excellent Peepcode screencasts. I’ve read a fair amount on testing up to now - Mark Pilgrim’s Dive Into Python is very good on the subject - but it was Geoffrey’s material that really clicked with me. (I’m watching his Capistrano one at the moment, and it’s certainly proving to be as good as the testing one).

I’ve always understood the point - and the utility - of test suites, but I’m pleased to have got my head around writing my own, starting with one (of several) projects on the back burner. Small steps at first, but it’s really satisfying to be working in a relatively test-driven manner.

And so I’ve been enjoying watching the dots fly by before those magic words come up: 0 errors, 0 failures. The Peepcode screencasts come strongly recommended, as well. Here’s to slightly more watertight code from now on.

10
December
2006

Handling IE specific stylesheets with a Rails plugin

Time to announce my first published Rails plugin: ie-specific. And, more importantly, time to explain it.

I work as a front-end developer for a large scientific publishing firm. We’re very much committed to standards compliance and accessibility, as such, make every effort to ensure our sites work in as many browsers as possible. And that includes Internet Explorer 5.

Now, prior to IE7, we did this (by and large) by producing standards-compliant stylesheets, and then adding browser hacks where they were the only solution, in order to achieve consistent look/feel in many browsers. Fast forward to IE7, and we’ve now got a problem: many browser hacks (notably * html) no longer work in IE7 and yet it still has its own raft of styling quirks.

So we’ve decided to change the way we implement browser-hacking. On the project I’m currently working on, we now have a main.css which contains all the standards-compliant, “correct” CSS. We then place the IE-specific styles inside IE conditional comments. Each browser version gets a css file of its own where necessary, named for the name of the relevant IE conditional filter - eg, lte-ie-6.css, ie-6.css, lte-ie-5.500, etcetera.

When I started work on the front-end integration for this Rails project, it was clear that this was obviously something that could be automated in Ruby - and, given that we were probably going to use it again, it made sense to package it as a plugin so that the next time I came to need it for a project, a quick script/install would be enough.

Enter ie-specific, currently hosted at Google Code given that a) it’s open-source and b) it’s an easy way to get anonymous public svn.

It’s really simple. First, install the plugin:

script/plugin install http://ie-specific-rails-plugin.googlecode.com/svn/ie-specific

Now, place any IE-specific stylesheets into #{RAILS_ROOT}/public/stylesheets/ie_specific, named with the appropriate conditional filter (eg: lte-ie-6.css). Similarly, you can place IE-specific javascript into #{RAILS_ROOT}/public/javascripts/ie_specific. We use IE-specific Javascript to simulate min/max-width capabilities in Internet Explorer.

Finally, in the <head> of your layout, include the following ERb:

<%= ie_specific_styles_and_scripts %>

Each file in the ie_specific directories will be automatically included inside appropriate conditional comments - CSS files will be imported via an @import directive, and JS files will be appropriately escaped as CDATA (important for us, because we write XHTML 1.0 strict). There’s no unnecessary duplication, either - lte-ie-6.css and lte-ie-6.js will automatically be placed inside the same conditional comment.

That’s it, really - it’s very simple, but it’s also a convenient way to keep markup and styles clean and let other developers know exactly what’s a hack and what’s not. For more info, check out the README. And let me know what you think!

Links & notes for this month

Endnotes