Learning Ruby reimplementing it: attr_writer

This is how attr_writer may be (re)implemented:

module Kernel
  def attribute_writer(attribute)
    define_method("#{attribute}=".to_sym) do |value|
      instance_variable_set("@#{attribute}", value)

class MyClass
  attribute_writer :my_attribute

m = MyClass.new
m.my_attribute = 23

puts m.instance_variable_get "@my_attribute" # => 23

Learning Ruby reimplementing it: attr_reader

How handy is the attr_reader method? Very handy indeed.

Never asked yourself how it may be implemented? Just do it!

This is my take:

module Kernel
  def attribute_reader(attribute)
    define_method(attribute) do

class MyClass
  attribute_reader :my_attribute

m = MyClass.new
m.instance_variable_set("@my_attribute", 42)

puts m.my_attribute # => 42

What’s yours?

Have fun!

A Rails project file for Sublime Text 2

The simplest thing that you can do to open up the Sublime Text 2 editor on your Rails project is to just type in

$ subl .

on the Rails root directory¹.

A slightly better solution is to create a .sublime-project file in your project root directory, so that you may launch the editor with something like

$ subl --project my_rails_project.sublime-project

A question then arises, “How do I exclude useless directories as tmp or log from the project file?”

Answer: just edit the sublime-project file this way:

     "path": ".",
     "folder_exclude_patterns": ["tmp", "log"],
     "file_exclude_patterns": [".tmtags"]

(and of course you should adapt it to your actual preferences on what to exclude from your project).

Note that you can also specify a “file_exclude_patterns” property to filter out some files (in my case I wanted to exclude the ctag index file).

  1. to install the command line tool, just follow the docs here.

Dynamically add data accessor methods on “static” Rails data model

An useful metaprogramming spell I recently played with is the Module#define_method(), which dynamically adds an instance method to the class on which is called.


I found it particularly useful to add data accessor methods on “static” Rails data model: suppose I’m working an e-commerce Rails webapp, and I have a Country model which maps the countries suitable for shipping, or a PaymentType model which represents all the possible payment types.

For these kind of models (and tables), which are typically static (they don’t change often), you often have to access specific values, say Country.italy or PaymentType.credit_card.

In these cases, defining dynamically an accessor method may be useful and more clear than always perform a find_by_name("my value").

So, for example, I open up my country.rb model class and add these lines

class << self
  Country.all.each do |each_country|
    define_method(each_country.name.downcase.gsub('.', '').gsub(' ', '_')) do

And then opening the Rails console I will be able to type

1.8.7@epistore > Country.sri_lanka
# {
                :id => 59,
              :zone => "U9",
           :enabled => true,
        :created_at => Tue, 20 Apr 2010 17:01:45 CEST +02:00,
        :updated_at => Tue, 20 Apr 2010 17:01:45 CEST +02:00,
          :iso_code => "LK",
    :country_set_id => nil

Just a note: as I said, Module#define_method() will add an instance method on the class. To add a class method, which is what I want, we have to use a different approach, using the class << self syntax to add a singleton method in the receiver.

I may also add a query method on each Country instance to check that country against another country (for example, I may ask my_country.italy?)

  Country.all.each do |each_country|
    define_method(each_country.name.downcase.gsub('.', '').gsub(' ', '_').concat('?')) do
      has_iso_code? each_country.iso_code

And then, after issuing a reload! command in the Rails console, I may type:

1.8.7@epistore > Country.usa.usa?
1.8.7@epistore > Country.usa.italy?
1.8.7@epistore > Country.usa.south_korea?
1.8.7@epistore > Country.south_korea.south_korea?

Depending on the kind of Rails app you have, these may be a useful tip.

Ruby: how to spot slow tests in your test suite

This is actually my first post in english and also my first post on Ruby/Rails stuff. Twice as hard!

Anyway, we’re working on a Rails project, and we’re experiencing the classical debate in all Rails project (at least the ones with tests!): why our test suite is so damn slow?!
Ok, we know that ActiveRecord is one of the key components in Rails and is at the root of its philosophy of web development. And along with ActiveRecord comes the strong tight between the model and the database. So each test, even the unit tests, will touch the database (ok, technically speaking they cannot be defined unit-tests, I know. Sorry Michael Feathers for betraying your definition).
The very first consequence of this approach is that as your test suite grows with your project, it will become slower and slower.

Let’s take our current project. This is our actual test suite composition:

  • Unit: 317 tests, 803 assertions
  • Functional: 245 tests, 686 assertions
  • Integration: 50 tests, 218 assertions

So we have 612 test methods, for a resulting number of 1707 assertions.
As a side note, our code-to-test ratio is 1:2.3, that is, for each line of production code we have 2.3 lines of tests.
The suite takes about 115 seconds to execute (on my MacBook Pro Core 2 Duo).

So, what can we do to speed up our tests and have a more “feedback-friendly” test suite?
The first step toward the solution of this issue is to have some metrics to reflect on, and so I developed this little ruby module to collect test duration times.
This is how you can use it too:

First, create a file called “test_time_tracking.rb” in the test folder of your Rails project. This should be its content:

module TestTimeTracking
    class ActiveSupport::TestCase
      def self.should_track_timing?

      setup :mark_test_start_time if should_track_timing?
      teardown :record_test_duration if should_track_timing?

      def mark_test_start_time
        @start_time = Time.now

      def record_test_duration
        File.open("/tmp/test_metrics.csv", "a") do |file|
          file.puts "#{name().gsub(/,/, '_')},#{Time.now - @start_time}"


Then, edit your “test_helper.rb” (again, under the test folder), to require and include the previous module.


ENV["RAILS_ENV"] = "test"
  require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
  require "test_time_tracking"

  class ActiveSupport::TestCase
    include TestTimeTracking

then, all you have to do is executing your rake task with the “tracking” option set, e.g.
tracking=on rake

At the end of the test suite execution you’ll find a CSV file (test_metrics.csv) in your /tmp folder.
This file contains a line for each test method executed, along with its duration in seconds.
I use to upload this file in google docs, and then apply a formula to sort out the methods from the slowest to the fastest.
A good formula is the following:
=Sort(A2:B612, B2:B612, FALSE)

The main limitation in the current implementation of this module is that every time the suite is executed with rake, the new time metrics collected are appended at the end of the previous file (if it exists), so each time you should remember to move the file to a different location. I’m working on this issue, so I’m expecting to find a better solution. Stay tuned!