Aimred Developer Blog http://www.aimred.com/news/developers The Aimred Development Blog is where our developers discuss the latest technologies and methodologies they're using while working on projects and solutions. From Ruby programming techniques to software engineering methodologies and everything in between you can find it here. Sat, 22 Nov 2008 23:19:46 +0200 webmaster@aimred.com (Aimred Webmaster) webmaster@aimred.com (Aimred Webmaster) A Quick Cautionary Tale http://www.aimred.com/news/developers/2008/11/22/a-quick-cautionary-tale Sat, 22 Nov 2008 23:08:25 +0200 http://www.aimred.com/news/developers/2008/11/22/a-quick-cautionary-tale Just a quick word of warning, when you want to write
array = [ 1, 2, 3, 4 ]

don’t write

array = { 1, 2, 3, 4 }

the latter in fact being equivalent to writing

array = { 1 => 2, 3 => 4 }

and will keep you up till 3am trying to understand why your code is broken.

]]>
November Cape Town Ruby Brigade http://www.aimred.com/news/developers/2008/11/09/november-cape-town-ruby-brigade Sun, 09 Nov 2008 22:22:41 +0200 http://www.aimred.com/news/developers/2008/11/09/november-cape-town-ruby-brigade The November meeting of the Cape Town Ruby Brigade is this coming Wednesday.

Talks:

  • ‘Irbie – A Ruby IRC Bot’ by Jonathan Groll
  • ’What’s New In Ruby 2.0’ by Farrel Lifson

Venue: Bandwidth Barn Meeting Room, 125 Buitengracht, Cape Town
Date: Wednesday, 12th November 2008
Time: 19:00

]]>
A Workaround To A Near Miss Part II http://www.aimred.com/news/developers/2008/11/04/a-workaround-to-a-near-miss-part-ii Tue, 04 Nov 2008 16:39:49 +0200 http://www.aimred.com/news/developers/2008/11/04/a-workaround-to-a-near-miss-part-ii Following on from my previous article here’s a slightly neater way to combine Proc#=== and Symbol#to_proc. No special functions required.
1 case number
2 when lambda( &:even? )
3   puts "Even!"
4 when lambda( &:odd? )
5   puts "Odd!"
6 when lambda( &:zero? )
7   puts "Zero!"
8 end

]]>
A Workaround To A Near Miss http://www.aimred.com/news/developers/2008/11/02/a-workaround-to-a-near-miss Sun, 02 Nov 2008 22:11:35 +0200 http://www.aimred.com/news/developers/2008/11/02/a-workaround-to-a-near-miss In my previous article I discussed how I thought Symbol#to_proc and Proc#=== would work nicely together but ran into syntax and semantic issues. Here’s how to get round that using a function that returns dynamically created Proc objects.

 1 def it_is( property )
 2   Proc.new{ |object| object.send( property )}
 3 end
 4 
 5 case number
 6 when it_is( :even? )
 7   puts "Even!"
 8 when it_is( :odd? )
 9   puts "Odd!"
10 when it_is( :zero? )
11   puts "Zero!"
12 end
]]>
Proc#=== + Symbol#to_proc = A Near Miss http://www.aimred.com/news/developers/2008/10/30/proc-and-symbol-to-proc-a-near-miss Thu, 30 Oct 2008 00:06:23 +0200 http://www.aimred.com/news/developers/2008/10/30/proc-and-symbol-to-proc-a-near-miss Here’s a an application of combining my Proc#=== suggestions and Rails’ Symbol#to_proc, both now part of the core library in Ruby 1.9, that I thought of this morning.

1 case number
2 when :even?.to_proc
3   puts "Even!"
4 when :odd?.to_proc
5   puts "Odd!"
6 when :zero?.to_proc
7   puts "Zero!"
8 end

which is equivalent to writing

1 if number.even?
2   puts "Even!"
3 elsif number.odd?
4   puts "Odd!"
5 elsif number.zero?
6   puts "Zero!"
7 end

Although I will admit the if/elsif example is more readable, mainly because of the presence of all those (unecessary) to_procs. Ideally I would liked to have been able to write the when clauses like

1 when :even?
2   puts "Even!"

and so on without those to_procs all over the place.

I initially thought about defining Symbol#=== as

1 class Symbol
2   def ===( *values )
3     self.to_proc.call( *values )
4   end
5 end

but it has implications if we’re using === to compare two Symbols, as there is no way to differentiate if we want to merely compare them using == (as the behaviour is now and which is perfectly logical and correct) or if we want to use the new Symbol#=== functionality defined above. So I’ll admit this is a near miss in terms of Ruby dynamic language coolness.

]]>
A Caution On Literal Symbols http://www.aimred.com/news/developers/2008/10/22/a-caution-on-literal-symbols Wed, 22 Oct 2008 01:06:09 +0200 http://www.aimred.com/news/developers/2008/10/22/a-caution-on-literal-symbols I learned early on in my software engineering career that passing around literal strings in code is a very bad idea especially if that string is being used to control logic. A single misplaced letter in that string and before you know it it’s 3:27am and you’re wondering why the output of your parser is hopelessly incorrect.

A growing trend in the Ruby/Rails community however has been to pass around symbols as method arguments, but because symbols are compared as if they are strings this can dangerous as well. I’ll illustrate this in the following snippet from an IRb session:

 1  >> def foo( bar )
 2  >>   puts "Baz!" if bar == :bar
 3  >> end
 4  => nil
 5  >> foo( :bar )
 6  Baz!
 7  => nil
 8  >> foo( :ber )
 9  => nil
10  >> BAR = :bar
11  => :bar
12  >> foo( BAR )
13  Baz!
14  => nil
15  >> foo( BER )
16  NameError: uninitialized constant BER

In this example on lines 5 and 8 we call the function with a literal symbol except on line 8 it’s misspelled. The result for line 8 is that nothing is output, but with no indication that something is wrong. On line 10 we assign the symbol to a constant and then on lines 12 and 15 we again call the function passing the constant but with a similar mispelling on line 15. This time however a NameError is raised and we are notified that there is something wrong with our code.

It pays to double check your code if you use lots of symbols and consider using constants in places where symbols control important logic. It’s easy to press the wrong key, but can be hard to correct if that mistake is buried deep in your code.

]]>
Arguments For Rake http://www.aimred.com/news/developers/2008/10/16/arguments-for-rake Thu, 16 Oct 2008 13:56:47 +0200 http://www.aimred.com/news/developers/2008/10/16/arguments-for-rake Sometimes it pays to read the release notes. If I did that more often I would have known that as of Rake 0.8.0 it’s possible to pass arguments to rake tasks on the commandline. I first read about it in this article (via ruby.reddit.com) and applied it to the article I wrote previously on code generation. All it entailed was changing

1 task( :model_auto_rspec => 'sequel:merb_start' ) do
2   model_class = ENV['model']

to

1 task( :model_auto_rspec, :model , :needs  => 'sequel:merb_start') do |task, args|
2   model_class = args.model

and calling it from the command line like so

1 rake generate:model_auto_rspec[User]
]]>
Making ERb (Slightly) Less Ugly http://www.aimred.com/news/developers/2008/10/15/making-erb-slightly-less-ugly Wed, 15 Oct 2008 01:26:20 +0200 http://www.aimred.com/news/developers/2008/10/15/making-erb-slightly-less-ugly In researching my previous article on code generation I came across a feature of ERb I’d never known about which makes ERb a bit more pleasing to the eye. Usually when I’ve written ERb template in the past it has looked like

1 <% 5.times do |i| %>
2 <%= i %>) hello
3 <% end %>

but if you instantiate ERb with the correct trim_mode string like so

1 ERB.new( template, nil, "%" )

then you can rewrite the previous template as

1 % 5.times do
2 <%= i %>) hello
3 % end
]]>
Overcoming Inertia: Autogenerating Specs With ERb And Sequel http://www.aimred.com/news/developers/2008/10/14/over-coming-inertia-autogenerating-specs-with-erb-and-sequel Tue, 14 Oct 2008 15:38:27 +0200 http://www.aimred.com/news/developers/2008/10/14/over-coming-inertia-autogenerating-specs-with-erb-and-sequel Momentum is an important factor when programming. Once you’ve been coding for a while momentum takes over and before you know it it’s 2:15 in the morning and you’ve got 248 tests passing without a hitch.

The enemy of momentum however is inertia,that initial hump you need to get over to get the code ball rolling. Many an hour has been wasted by a developer staring at an empty Vim window, trying to decide whether to write ‘class User’ or ‘class Member’ or ‘class Subscriber’, not to mention deciding what needs to be tested etc etc.

Sometimes you just need a kick in the coding pants to get things going and what better way to deliver the aforementioned kick than to use the built-in introspection of Sequel::Model to extract information about a models attributes and then our trusty friend ERb to autogenerate some RSpec testing code to get you started!

Note: Don’t forget to read this article to see how to implement improved command line arguments for Rake tasks.

First let’s look at the command that we run to kick everything off:

1 $ rake generate:model_auto_spec  model=User

We call a Rake task and pass through an environment variable containing the model we wish to generate our specs for. Let’s look at the Rake task:

 1 require 'erb'
 2 
 3 namespace :generate do
 4   desc 'Generates an rspec skeleton for a model'
 5   task :model_auto_rspec => 'sequel:merb_start' do
 6     model_class = ENV['model']
 7     model_instance_name = model_class.downcase
 8     model_file = "#{ Merb.config[ :merb_root ] }/app/models/#{ model_instance_name }"
 9     model_spec_file = "#{ Merb.config[ :merb_root ] }/spec/models/#{ model_instance_name }_auto_spec.rb"
10     model_instance = "@#{model_instance_name}"
11     template_file  = "#{ Merb.config[ :merb_root] }/lib/tasks/rspec_model_skeleton.erb"
12     model = Object.const_get( model_class )
13     File.open(template_file,"r") do |input|
14       File.open( model_spec_file, "w" ) do |output|
15         output.puts( ERB.new( input.readlines.join, nil, "-" ).result( binding ))
16         puts "Wrote auto generated rspecs to #{ model_spec_file }"
17       end
18     end
19   end
20 end

In lines 6-11 we set up our environment, constructing the names of the various files we’ll use, for instance the generated specs will be written to ‘spec/models/user_auto_spec.rb’. On line 12 we use Object.const_get to retrieve the actual class from the class name. Starting on line 13 we read in our template file, which for models is ‘rspec_model_skeleton.erb’ and use ERb to parse it and generate our finished file.

It’s a good idea to write the auto-generated specs to a seperate file than ‘spec/models/user_spec.rb’. That way we can regenerate the specs in ‘user_auto_spec.rb’ later on and not wipe out the handwritten specs in ‘user_spec.rb’.

Here’s part of the contents of a template file which generates some tests for a model that has been saved for the first time to the database:

 1 describe <%= model %>, "which has been initially saved" do
 2   before{ <%= model_instance %> = create_<%= model_instance_name %> }
 3   after{ clear_all_tables }
 4 
 5   it( "should be valid" ){ <%= model_instance %>.should be_valid }
 6   <%- model.db_schema.each do |column,column_info| -%>
 7   <%- unless column_info[ :allow_null ] -%>
 8   it( "should have a non null <%= column %>" ){ <%= model_instance %>.<%= column %>.should_not be_nil }  
 9   <%- end -%>
10   <%- end -%>
11 end

On line 6 we use Sequel::Model#db_schema to interrogate the database table and retrieve information about each column, which is returned in the column_info hash. We’re only interested in testing the attributes that are required to not be null and so on line 7 we we use the column_info to generate requirements only for attributes which have
column_info[ :allow_null ] == false

And after all is said and done the generated code looks like this:

 1 describe User, "which has been initially saved" do
 2   before{ @user = create_user }
 3   after{ clear_all_tables }
 4 
 5   it( "should be valid" ){ @user.should be_valid }
 6   it( "should have a non null password_hash" ){ @user.password_hash.should_not be_nil }  
 7   it( "should have a non null created_at" ){ @user.created_at.should_not be_nil }  
 8   it( "should have a non null updated_at" ){ @user.updated_at.should_not be_nil }  
 9   it( "should have a non null username" ){ @user.username.should_not be_nil }  
10   it( "should have a non null id" ){ @user.id.should_not be_nil }  
11   it( "should have a non null uuid" ){ @user.uuid.should_not be_nil }  
12 end

create_user and clear_all_tables are helper methods defined in our spec helper files.

As you test other models you’ll pull out common tests that apply across models and add them to your template file. Regenerating the auto spec files will then test your previously written models with the new tests as well.

So there you have it. No more needlessly fighting coding inertia, just a few keystrokes at the command line and you’re A for Away.

]]>
October Ruby Brigade Meeting http://www.aimred.com/news/developers/2008/10/06/october-ruby-brigade Mon, 06 Oct 2008 23:29:10 +0200 http://www.aimred.com/news/developers/2008/10/06/october-ruby-brigade Here are the details for the October Ruby Brigade Meeting.

When: 19:00, 8th October 2008
Where: Bandwidth Barn, 125 Buitengracht St, Cape Town
Who: Nick Coyne on i18n in Rails 2.2 and Joerg Diekmann on architecting Blinkplan.

]]>