I'm all about Ember.js recently

Why I Love Datamapper

I wanted to find the last user in alphabetic order of their names in a Merb project that uses Datamapper (the default ORM in Merb). So I did [*]:

irb(main):020:0> User.all(:order => [:name]).first.name
 ~ (0.032946) SELECT  FROM `users` ORDER BY `name` LIMIT 1
=> "Admin User"

Ok, so the default sorting order is ascending but I need the last one. There are two ways to do this. Write an SQL snippet and sneak in “DESC” somewhere or reverse the collection before taking the first element. Since I was not sure how to sneak in “DESC” plus I prefer writing Ruby to writing SQL hands down, I went with the second approach:

irb(main):021:0> User.all(:order => [:name]).reverse.first.name
 ~ (1.033271) SELECT  FROM `users` ORDER BY `name` DESC LIMIT 1
=> "XX XX"

See what happened? Instead of reverting the collection (which is extra time even if it is done very fast) Datamapper sneaked in that DESC for me! Isn’t this just brilliant? Datamapper takes the burden to write SQL off of your shoulders. You can keep writing Ruby statements you presumably love and let Datamapper take care of the SQL reaping both the comfort and the performance gain. [**]. Also, likewise your app stays database type agnostic. Note how it is not supposed there is a RDBMS under the ORM layer. It could work with CouchDB, for example (I think there is actually work in progress for a CouchDB adapter). This is not the only reason I like Datamapper so much, so if you are still not convinced, go check out some other reasons to use it.


Notes

* I could have written this one in a simpler way:

irb(main):018:0> User.first(:order => [:name]).name
 ~ (0.032345) SELECT  FROM `users` ORDER BY `name` LIMIT 1
=> "Admin User"
But you -or at least I- could not do it for the last element (there is no User.last)

** I am not suggesting not to learn SQL at all. I am all for a know-thy-tools approach (especially it it means not cluttering your markup with javascript :) ). However, having the ORM do obviously good things for you is worth it most of the time.

Deep_test to Become TDD More Easily

I am all for TDD, really. I did not even waver when recently I have been working on a medium-sized Rails project and running the tests after each change took about 60-80 seconds. 60 seconds is still a lot, though, especially if you go through these cycles ~50 times a day (a wild guess). I also believe in very short test-implementation cycles to stay focused so I was starting to think about ways to keep that time down.

Autotest, part of the Zentest toolbox is a very good choice. It basically runs all the tests automatically after something has changed in the code and more importantly it only runs the tests it deems affected by the latest change. This helped to reduce the amount of time by reducing the number of tests that were run in each loop.

Another I think less well-known option is deep_test which helps to reduce testing time by increasing computational power. More precisely, it runs the tests through worker threads so you can either benefit from using deep_test if you set it up for a computer network (individual computers take from a pool of tests and then send in the results) or if you have a multi-core computer. Since many of us do nowadays, that stepped up as a viable option.

It was quite easy to set up and the results it brought were quite remarkable. It reduced the running time of my tests by ~40% (based on a completely unscientific benchmark). One thing I experienced is that it did not really play out well with sqlite although I have not spent a lot of time trying to make it work there. I just switched to mysql and it worked seamlessly. So yeah, the next logical step was to get the better of both worlds: run only the tests that need to be run and run them on as many cores as possible. I will talk about that in a later post.

I would very much like to hear your experiences and solutions to make TDD a breeze or just plain bearable. I cannot imagine doing real TDD if running tests takes more than a certain time limit, around maybe 90 seconds. Not only you lose a lot of time waiting for the tests to finish, more importantly you fall out of the falling test-implementation cycle, you lose focus, your mind drifts away and then the whole thing probably just does not work.

Simple To-do List in Sinatra

After Bence Golda’s presentation at the last budapest.rb meetup I decided to build something easy in Sinatra since it seemed so cool and easy to do. And I have to tell you, it really is both.

With zero prior experience with Sinatra and only a bit of fresh HAML knowledge, my todolist was ready in a few hours. What can you do with it? Add todos to your list and delete them when you are done. What features does it have? Unobtrusive javascript :) What does it lack? Obtrusive javascript :) User-related funcionalities, the possibility of having more lists, seeing done todos, etc. Lots of things. But with the ease of development Sinatra provides I am sure that for a simple application like this these could be added quite quickly. And then tadalist.com would be running for its money :) (I know, it’s free).

ps. I use an ORM, datamapper to not to have to deal with SQL directly, so you’ll have to “gem install dm-core” beyond the sinatra gems if you want to run the app.

Strings as Haml Render Parameters in Sinatra Do Not Work

I was intrigued by the simplicity and elegance of Sinatra as presented by Bence Golda at the last budapest.rb meetup., so I decided to build a simple application with it (I am planning to talk just a little bit more about that in a later post).

One quick thing I learned the hard way is when generating haml views in Sinatra, you have to use symbols as the name of the view, strings will just be rendered as strings. That was a tough lesson to learn coming from Rails. So while in Rails you can write:

  def index
    render :action => :index
  end

or

  def index
    render :action => "index"
  end

In Sinatra, you can only use a symbol to designate the view to be rendered:

get '/' do
  haml :index
end

Which makes sense, I think, since symbols (unlike strings, see below) with the same name refer to the same entity which is a perfect fit for naming views, now ain’t they? Plus, I’ll admit I am in love with them symbols, with their colon in the front and all. And when they are syntax highlighted, I melt.

irb(main):002:0> sym1 = :index; sym2 = :index; sym1.object_id == sym2.object_id
=> true
irb(main):003:0> s1 = "index"; s2 = "index"; s1.object_id == s2.object_id
=> false

Shoulda: Setup and Should Blocks and Don’t Wander Off the Map

I’m using shoulda for testing in a rails project and I wrote this simple test to see if my update action really updated the object and redirected to the appropriate place:

context "the update" do
  setup do     # 1
    @project = Factory(:project, :director => @user)
    put :update, :id => @project, :project => { :name => "updated name" }
  end
  # 2    
  updated_project = Project.first(:order => "created_at DESC")
  # 3
  should_redirect_to "project_url(updated_project)" # 4
  should "update the attributes" do
    assert_equal("updated name", updated_project.name) # 5
  end  
end

To my surprise, I received an “undefined local variable or method ‘updated_project’ on both tests (#4 and #5). I figured out why and I want to share it with you. In case you are a shoulda expert, you must know the answer already and sorry for wasting your time. On the other hand, if you are new to shoulda like I am, you may find this useful.

What shoulda does when running a ‘should’ block is that it runs all the ‘setup’ blocks of the contexts in which it is nested, from the outside to the inside, so this:

context "alpha" do
  setup do
    puts "A"
  end
  context "beta" do
    setup do
      puts "B"
    end
    context "gamma" do
      setup do
        puts "C"
      end
      should "work" do
         puts "the only test"
      end
    end
  end
end

Will print

A
B
C
the only test

Also the area between #2 and #3 in the above test is sort of a no man’s land, since it is not in a setup block, so assignments that are executed here are completely useless. You can not use it either for side-effects since it will run before the setup block (#1 above). My advice is to simply put everything in a block, be it a ‘setup’ or a ‘should’ one. (the ‘should_redirect_to’ is a macro that’s part of shoulda, it gets expanded into a block, too).

So here is the same test correctly:

context "the update" do
  setup do
    @project = Factory(:project, :director => @user)
    put :update, :id => @project, :project => { :name => "updated name" }
  end
  
  should_redirect_to "project_url(@project)" 
  should "update the attributes" do
    # reload is needed to see the new state
    @project.reload
    assert_equal("updated name", @project.name)
  end
  
end

Shoulda is a nice tool. There is only one I know and I like a tad better which is quite similar in structure, rspec.

MySQL Table Types and Foreign Key Constraints

Uff, I have recently spent some time checking foreign key constraints in MySQL and I got a bit upset. The MySQL docs tell you that InnoDB tables support foreign key constraints but that’s not the same as saying MyISAM tables do not. More importantly, an error (or at least a warning) should be raised so that I am not relying on something that seems to be there when in fact it is not.

Here is the raw SQL:

CREATE TABLE `drivers` (
  `id` INT PRIMARY KEY AUTO_INCREMENT,
  `name` VARCHAR(100)
);


CREATE TABLE `cars` (
  `id` INT PRIMARY KEY AUTO_INCREMENT,
  `plate_number` VARCHAR(12),
  `driver_id` INT,
  FOREIGN KEY (`driver_id`) REFERENCES `drivers`(`id`) ON DELETE CASCADE
);

INSERT INTO drivers(name) VALUES ('bob');
INSERT INTO drivers(name) VALUES ('alice');
INSERT INTO cars(plate_number, driver_id) VALUES ('bbb', 1);
INSERT INTO cars(plate_number, driver_id) VALUES ('ooo', 1);
INSERT INTO cars(plate_number, driver_id) VALUES ('aaa', 2);
INSERT INTO cars(plate_number, driver_id) VALUES ('lll', 2);
mysql> delete from drivers where id=1;
Query OK, 1 row affected (0.00 sec)

mysql> select * from cars;
+----+--------------+-----------+
| id | plate_number | driver_id |
+----+--------------+-----------+
|  1 | bbb          |         1 | 
|  2 | ooo          |         1 | 
|  3 | aaa          |         2 | 
|  4 | lll          |         2 | 
+----+--------------+-----------+
4 rows in set (0.00 sec)
CREATE TABLE `drivers` (
  `id` INT PRIMARY KEY AUTO_INCREMENT,
  `name` VARCHAR(100)
) ENGINE=INNODB;


CREATE TABLE `cars` (
  `id` INT PRIMARY KEY AUTO_INCREMENT,
  `plate_number` VARCHAR(12),
  `driver_id` INT,
  FOREIGN KEY (`driver_id`) REFERENCES `drivers`(`id`) ON DELETE CASCADE
) ENGINE=INNODB;

INSERT INTO drivers(name) VALUES ('bob');
INSERT INTO drivers(name) VALUES ('alice');
INSERT INTO cars(plate_number, driver_id) VALUES ('bbb', 1);
INSERT INTO cars(plate_number, driver_id) VALUES ('ooo', 1);
INSERT INTO cars(plate_number, driver_id) VALUES ('aaa', 2);
INSERT INTO cars(plate_number, driver_id) VALUES ('lll', 2);
mysql> delete from drivers where id=1;
Query OK, 1 row affected (0.00 sec)

mysql> select * from cars;
+----+--------------+-----------+
| id | plate_number | driver_id |
+----+--------------+-----------+
|  3 | ppp          |         2 | 
|  4 | eee          |         2 | 
+----+--------------+-----------+
2 rows in set (0.00 sec)

I know very well one should read the manual before complaining but I also think software should complain if asked something which it is not capable of doing. -1 for MySQL.

Google Groups Tracker Using Yahoo Pipes

I -and I suppose most of my developer mates- am subscribed to many Google Groups. When there is a topic I am interested in or a problem I posted or replied to it would be cool to get notified of changes to it. Instead of checking it five times a day to see if someone has commented on it which also slices up the big, continuous chunks of time we programmers need. Also, some groups are littered by spam topics so it would be nice to filter out all the things you are not particularly fascinated about and be left with the things you are.

Unfortunately, Google Groups does not offer us the possibility of following certain topics (e.g by sending you an email whenever someone added his comment, a la Lighthouse). But there is a solution although I’ll admit the one I am describing below is not a particularly cunning or elegant one. If you felt the same pain and found a remedy, I am curious to know what it is, so please leave a comment.

So, as we all know, the Internet is just a series of tubes, so the idea to use Yahoo Pipes to cobble together something came quite naturally. Ladies and gentlement, I created the Googe Groups issue tracker. It is capable of tracking two Google groups. You can pass three strings for each one and it generates an RSS of the items whose title have any of the strings you provide.

I know it has many shortcomings (to say the least). What if you want to track issues for 3 groups or more? More than 3 issues per group? My puny tracker can’t do that right now since its “legoed” together from Yahoo Pipes building blocks and so it’s not programmable. You can, however, clone my pipe, expand it to handle more groups or more expressions, enter the groups you want to track and subscribe to the resulting RSS with your reader of choice.

It may still feel clumsy, since you have to regularly update your strings based on the issues you are interested in. I know a more general solution would be to hack together something that is more manageable and expandable which I might do soon. But it still feels so good from time to time to leave the serious, hard-thinking adult world and build Lego castles. So go ahead, don’t be shy, build your own castle and let me know about it! :)

UPDATE: Thanks to Bob, I realized Google has the very option I missed and constructed the pipe for :) However, there can still be some valid scenarios where it can be of service. As per Jaime’s comment I realized I did not really explain how to run the pipe, so let me do it through an example that is not too contrived:

Let’s suppose you are a DataMapper expert and you want to help those newbies/impatient people who put ‘help’ in the title of their post. In that case, you would input http://groups.google.com/group/datamapper in the “Group1 URL” box and “help” in the “Group1 - Title 1” field. At the pipe output you’d only see those posts which have help in their title, then.

If you want to also see announcements and the convention would be to have [DM] in the title of those posts, you would then enter “[DM]” in the “Group1 - Title 2” field.

To construct a filter which only lists ruby-quiz related posts on http://groups.google.com/group/ruby-talk-google is left as an exercise to the reader :).

A Ruby-style Currency Converter

Though it is said that we live in a highly-globalized world, all countries still have their own proper currency (with one exception that I know of, the euro) so we still need to convert between them. If one is used to shop online (and one is) the need to get the price in the national currency occurs quite often. Going to a currency converter page is not much of a hassle but it still takes too much time and it seemed an overshoot to use a browser for this task. Inspired by Rails’s date calculations extensions (where you could write 3.days.ago), I decided to create something similar and see how much flying to Barcelona or buying a PragProg book costs from the command line.


require "net/http"
require "open-uri"
require "hpricot"

# makes 1284.eur.to.usd types of queries possible
class CurrencyConverter
 
  Currencies = { :huf => "HUF", :eur => "EUR", :usd => "USD", :gbp => "GBP", :chf => "CHF" }
 
  # these methods "close" the quote.
  # when they are called, it means all data is ready
  # the quote can be sent.
  class_eval do
    Currencies.each_key do |curr|
      define_method curr do
        @to = curr
        calculate
      end
    end
  end
 
  def initialize(amount, from=nil, to=nil)
    @amount = amount
    @from = from
    @to = to
  end
 
  def send_request_for_quote
   from_as_param = @from.to_s.upcase
   to_as_param = @to.to_s.upcase
   url = "http://xurrency.com/#{[@amount, @from, @to].join('/')}/feed"
   doc = Hpricot(open(url).read)
   (doc/'dc:value').inner_html
  end
 
  def calculate
    send_request_for_quote
  end

  def to
    self
  end
 
end

class Fixnum 
  def method_missing(name)
    CurrencyConverter.new(self, name)   
  end
end

Thanks to ruby’s open classes, the code is quite terse (you can also see and download the raw script from here). Now you can fire up irb and do all the conversions you want:

$ irb -r currency_converter.rb 
irb(main):001:0> 23.eur.to.huf
=> "6473.3500"
irb(main):002:0> 1.usd.to.eur
=> "0.7642"

Or do it through the ruby interpreter:

$ ruby -r rubygems -r currency_converter.rb -e "puts 1.eur.to.usd"
1.3085

I find it very pleasing to be able to write “10.eur.to.usd” since it is so close to our spoken, human language. One of ruby’s numerous charms.

My friend, Peter sent a more general solution that uses html scraping with Scrubyt and the conversion capabilities of Google search:

require 'rubygems'
require 'cgi'
require 'scrubyt'

begin
google_converter = Scrubyt::Extractor.define do
  fetch "http://www.google.com/search?q=#{CGI::escape(ARGV[0])}+#{CGI::escape(ARGV[1])}+to+#{CGI::escape(ARGV[2])}"
  
  google_result "//td[@dir='ltr']" do
    final_result(/= (.+) /)
  end
end
  puts google_converter.to_hash[0][:final_result]
rescue
  puts "Sorry, even *google* can't translate that!"
end

Using this you can convert amounts between any two currencies (distances, weights, etc., everything that Google search can handle):

$ ruby conv.rb 30 EUR HUF

It may be swimming against the current but I like solutions that do not need the browser for simple problems like this one. I scratched my itch and hopefully scratched yours, too.

Record Your Bike Trips With Gmap Pedometer

Though I thought I would only post about technical issues here, I now make an exception. After all, (soft) rules are for breaking occasionally, aren’t they?

So in case you don’t know, there is a nice service out there to record your bike trips that I have recently discovered. It is a Google Maps application where you first search your point of departure then your point of arrival and Gmap Pedometer does the rest for you. Occasionally you have to lend it a helping hand, though, in case the automatic route generation does not work well. It usually does not if you take bicycle roads that does not run paralelly with the highway since the automatic route generation selects the “car route” by default (it seemed to me). You can set up your itinerary in no time and promptly see the distance you did and how much energy you burned during the process (and ultimately also the elevation of your trip).

I also grab the opportunity to tell you how bike tours are the perfect way of tourism for me. You can easily do 40-50kms per day in a moderate pace. In my opinion that’s a perfect middle ground between being too slow and passing by magnificent landscapes and towns in a car. What’s more, there is the thrill of riding your bike, feeling the air against your cheeks, the ability to stop anywhere and the ambiance of adventure that comes with the nomad lifestyle.

One thing I miss is a convenient method to store your trips. According to the site itself, Gmap Pedometer is “A hack that uses Google’s mapping application to help record distances traveled and calories burned during a running or walking workout.” so one should not expect a full-fletched, shiny application but a basic user registration/login method would be handy so I could quickly access my trips. To be able to review your trips, you must store the unique url that is generated for each one in a safe place.

To give you some example routes and also to store a pointer to some trips I would like to be able to access in the future I list the daily routes of two fairly recent bike routes:

The Netherlands (summer 2007)

Amsterdam - Den Haag Amsterdam - Enkhuizen Urk - Elburg Elburg - Appeldoorn (Beekbergen) Beekbergen - Arnhem (Oosterbeek)

Austria, going along the Danube (summer 2006)

Passau - Obernzell Obernzell - Feldkirchen Feldkirchen - Au an der Donau Au an der Donau - Willersbach Willersbach - Aggsbach Aggsbach - Krems

So what are you waiting for? Hop on your bike! :)

ps. Walking trips can also be recorded on the site and there is automatic route generation for walkers, too.

Ruby Metaprogramming: Call Counter - Take 2

So last time I left you with the promise that I’d return with a solution so that the number of times a certain method was called is a class method which makes more sense than if it was an instance method. So here is the “improved version”:

call_counter.rb:

module CallCounter
        
    def count_calls_to(method_name)
      original_method = instance_method(method_name)
            
      unless class_variable_defined?(:@@call_counter):
        class_variable_set(:@@call_counter, {})
      end
    
      call_counter = class_variable_get(:@@call_counter)
    
      define_method(method_name) do |*args|
        call_counter[method_name] ||= 0
        call_counter[method_name] += 1
        bound_original_method = original_method.bind(self)
        bound_original_method.call(*args)
      end

      metaclass = class << self; self; end
      metaclass.instance_eval do

        define_method(:calls_to) do |m|
          call_counter[m].nil? ? 0 : call_counter[m]
        end

        define_method(:reset_counters) do
          call_counter.each_key do |k|
            call_counter[k] = 0
          end
        end
    end
    
  end

end

What has changed is the introduction of a class variable that counts the calls on all watched methods and that the number of calls on each method is queried by calls_to(<method name>) instead of calls_to_<method_name>. A bit less magic.

call_foo.rb:

require "call_counter"

class CallFoo
    
  extend CallCounter

  def foo; "foo"; end
  def bar; "bar"; end

  count_calls_to :foo
  count_calls_to :bar

end

(a snippet of) call_counter_spec.rb:

require "call_foo"
require "spec"
    
describe CallFoo do
    
  before(:each) do
    @call_foo = CallFoo.new
    CallFoo.reset_counters
  end
        
  it "should be able to count several methods' calls" do
    4.times { @call_foo.foo }
    CallFoo.calls_to(:foo).should == 4
    7.times { @call_foo.bar }
    CallFoo.calls_to(:bar).should == 7
  end
    
end

I’m still not 100% content with this solution, the programming interface is nice now but it would be cool to get rid of the class variable somehow, possibly replacing it with closures. If you know how to achieve it, please leave a comment.

ps. You can also get the whole code in nice colored format or the raw text version.