Forgot to create a bunch of specs?
I got a little ahead of myself last week and wasn't a very good test first developer. I would like to say last week was the only time, and that I will never do it again. Being more realistic I wrote a little rake task that will create the missing model specs for me (just so they will show up in rcov/rspec reports and make me feel bad)
desc "create missing rspecs for all models"
task :create_missing_model_specs do
models = Dir.open("#{RAILS_ROOT}/app/models").collect {|file_name| file_name.split('.')[0] }
models.each do |model|
if model && model.size > 0
spec_path = "#{RAILS_ROOT}/spec/models/#{model}_spec.rb"
unless FileTest::exist?(spec_path)
puts "creating missing #{model} spec"
File.open(spec_path, "w") do |f|
f.puts "require File.dirname(__FILE__) + '/../spec_helper'"
f.puts "module #{model.camelize}Methods"
f.puts "end"
f.puts
f.puts "describe #{model.camelize} do"
f.puts "\tit \"should have boat-loads of coverage\""
f.puts "end"
end
end
end
end
end
Probably not the cleanest implementation, but I'm doing this to save time, not waste it!
permalink
Sending post commit emails with Subversion in ruby
I found a svn post commit email script floating around but it relied on sendmail. I changed it to use Net::SMTP so it would work with my postfix setup.
You can find it on pastie.
permalink
Using proper english at RejectConf Berlin
So I presented this little snippet at RejectConf last night. It's just a quick hack I wrote at lunch after dr. nic presented his meta-programming magic.
I wanted to write this because ever since I was 11 (when I learned BASIC) I've been using the american COLOR when I really meant COLOUR. Which isn't great
class Object
def method_missing(meth, *args, &block)
proper_english = { 'colour' => 'color',
'pluralise' => 'pluralize',
'metre' => 'meter' }
american_method_name = proper_english[meth.to_s]
if american_method_name
puts "** Using the proper english to call method #{american_method_name}"
return self.send(american_method_name, *args, &block)
end
super
end
end
permalink
I work on the web
Lisa Herrod has started a bit of a meme with the "i work on the web" photos popping up on flickr.
It's really cool to get a more personal view of all the people working in our space. I've put mine up and I recommend anyone else working on the web does the same.
EDIT:Tim has whipped up a homepage for this thing, you can find it at iworkontheweb.com. Very cool stuff, mad props to Tim, Lisa, and Lach for getting this happening.
permalink
New blog in Camping!
I've recently changed hosting for my blog and I thought this would be a wonderful chance to learn the camping framework and write it myself.
Development was easy enough - deploying when you don't have any internet at home to plug your laptop into and your workplace blocks every port - not so easy.
There are still a few bugs and I haven't implemented feeds just yet but I'll get to those as soon as I get a minute. Planning for the Norway move and wrapping things up at work is taking up a lot of time.
EDIT: Please note that some of the dates in the atom feed are a bit messed up. I didn't alter any of the dates when I imported my wordpress articles. Everything should be good soon.
permalink
And now with audio - Melbourne Ruby Nuby night redux
Marty from cogent consulting was kind enough to record screencasts of all our presentations from the Ruby Nuby night. Cogent are also being super nice and hosting them all on their screencasts page.
I've also put mine up on youtube to get a widget - which after a number of unsuccessful attempts should now be embedded below.
permalink
Introduction to Rails at the Melbourne Ruby Nuby night
Last night we ran the inaugural Ruby Nuby night at the Melbourne Ruby users group. The night was a massive success with about 50 people in attendance. The night was organised into two halves, a Ruby half and a Rails half, punctuated by a pizza and softdrink break.
I did the general introduction to Rails; I wasn't aiming for anything technical, I just kept it high level to try and interest people in Rails. I've put the slides down below. EDIT: A more recent post has the youtube presentation
I will probably get a reputation as the guy who called DHH a tool (in a recorded talk no less!) so I think I should put it in context. DHH is a super smart guy who has built what I believe to be the best web framework around so massive kudos is deservedly thrown his way. I just get tired of the massive flamewars that spark up around DHH a little too often to be called coincidences. When you're out there trying to get people on board with the new framework it becomes a bit of an embarrassment when the developer corner of the internet gets caught in a week long pissing contest.But mostly I was just going for a cheap laugh.
permalink
Presentation at webjam
Monday night (25th June, 2007) I presented alltimetop5 at webjam. I was lucky enough to meet the guy who runs these, Lachlan at Railscamp the other weekend who signed me up. It was a little weird getting up in front of a whole bunch of Microsofties to present a rails app but it went down well. I ended up getting third place in the voting for best presentation. The prize was a Wacom tablet that I'm having a lot of fun playing with.
I've put the slides up on slideshare and embedded them below.
permalink
Alltimetop5 is up
It's launched into public beta I guess. I've been iterating over it like crazy in the past week or two with all the feedback I've gotten so far. There is still a long way to go.
Go Check it out at http://alltimetop5.com
Send all the feeback to alltimetop5site[at]gmail[dot]com, I need to know how people are using it so I can improve on the features and usability.
permalink
Trouble installing mysql bindings on a MacBook?
Twice now I have had this problem while building native mysql bindings on my MacBook. I'm running OSX 10.4.8 and I can't remember which version of the xcode tools.
When you try and compile your bindings you will get an error message saying something like "ulong is undefined". The first time I got it was building the ruby mysql lib and I got it again this weekend building the perl dbi::mysql package.
The quickest workaround is to just do a quick search of the source file that threw the error - in the case with ruby it was mysql.c somewhere deep in my gems directory. Find the header file, mysql.h in this case, and insert the line
#define ulong unsigned long
That did the trick in both cases. I'm glad I remembered it from the last time I saw it, I don't have the internet at home and had to get some Perl work done - CPAN is very very difficult to work with on just a few flying visits to cafes with wifi.
permalink
Performance increase in C# 2.0 using generics
I've spent the past couple of days doing some fairly intense performance optimization at work. We have a C# implementation of a bayesian classifier that was written in the 1.1 version of the framework. Recently we've had a need to use it in a high volume situation and the performance wasn't quite up to scratch, the average time to classify was about 700ms. The past couple of days worth of benchmarking, profiling, testing, and tuning has gotten the run down to 30ms.
Short version of the story: the bulk of the performance increases came from tweaking some string manipulation and... generics. Quite a unique C# performance story right there.
Most of the value we got out of generics was in the implementation of our compressed sparse vector implementation.
The original implementation was a thin-ish wrapper on a hashtable all designed to hold word - frequency counts. The compression is provided in this way:
public double this[string key]
{
get {
if (InnerHashtable.ContainsKey(key))
{ return (double)InnerHashtable[key] }
else { return 0.0d } }
set { InnerHashtable[key] = value; }
}
When that code is run thousands and thousands of time all that boxing/unboxing becomes quite a hassle. I ended up refactoring the class to inherit from Dictionary which allowed me to removing all the casting there and also gave the chance to iterate over KeyValuePair<string, double> rather than the DictionaryEntry that I had to deal with before then.
The other big perfomance gain was in moving from IComparer to IComparer<T>. The previous comparer I was dealing with was to compare the values (not the keys) stored in two dictionary entries. The old method had 4 casts, 2 to convert the "objects" being compared to DictionaryEntry references, then another 2 more to cast the DictionaryEntry values to doubles. That adds up to 5 lines of code, 4 of which are casts just to perform a simple comparison (of which you're doing thousands). I replaced this with a IComparer<KeyValuePair<string, double>> which left me with just one line, a very neat and tidy strongly typed comparison.
To me it seems generics can give some real performance benefits. I have read that null checks against T can be very, very expensive (I can't remember where sorry) so if your comparer has to included some null checks you might be better off sticking with a non generic implementation. When carrying out this kind of work the important thing to do is test, test, test, profile, and test. I got probably 40% of my performance boost just in tidying up string manipulation code that my profiler picked up. Big gains for very cheap work there.
For the profiling I was doing I used dotTrace profiler which I found invaluable. dotTrace generates some very readable snapshots and makes it easy to compare each incremental improvement you make.
Sorry I haven't included more code with this article, but it's work code and not really mine to share. I just wanted to highlight where the high yield performance increases came from. Hope you find it helpful.
EDIT: First time around, I forgot to escape all the < and >
EDIT AGAIN: Jesus, this wordpress thing really hates code snippets, i've tidied up the formatting but it's still ugly.
permalink
Dealing with multiple models and validation in one view
I had been having a little trouble with validating multiple child models when creating/editing the parent. Error messages were unintelligible and a little annoying. Ed Thomson has a pretty good idea for tidying up those ActiveRecord::Errors but it was a little too specific for me. I've now made a more general method for tidying up the error messages which I put in the ApplicationHelper.def tidy_error_messages(model, included_model_names)
new_errors = ActiveRecord::Errors.new(nil)
model.errors.each do |key, message|
new_errors.add(key, message) unless included_model_names.include? key
end
# re-jig the errors for the included models
for included_model_name in included_model_names
for included_model in model.send(included_model_name)
included_model.errors.each do |key, message|
# use a custom error message if the model supports it
if included_model.respond_to? :create_error_message
included_model.create_error_message(new_errors, key, message)
else
new_errors.add(included_model_name, "#{key} #{message}")
end
end
end
# wipe out the old errors and chuck the new ones in
model.errors.clear
new_errors.each do |key, message|
model.errors.add key, message
end
end
This gives me a nice general solution that I can use in all of my models. If I want a custom message for any of my included models I just have to define create_error_message on the model. If I can't be bothered then there is a nice default message that will be created instead.permalink
login
