Skip to navigation

Super-simple mocking

Published January 10, 2007

Sometimes you want to modify a model’s behaviour for different environments.

For example, you may have a Comment#is_spam? method which goes off to Akismet and checks whether it’s spam. In development you might want the method to always return true, preventing it from calling Akismet. In other words we want to “mock” the Comment#is_spam? method whilst in development.

The stock-standard Pickaxe way of doing this might be to “reopen” your model class and add the method:


class Comment
  def is_spam?(permalink); false end
end

There’s nothing exactly wrong with this method, but you have to remember that Rails lazily loads everything. If you want to alias a method, or do some other manipulation on the class, you can’t because it doesn’t yet exist.

You’ve probably used the above method just fine on one of Ruby’s core classes, such as Time. Ruby has already require’d the Time class before your code executes so you don’t need to worry about whether it exists or not.

One possible fix for the lazy loading is to reference the Comment class before you manipulate it:


Comment # Rails will find and require your model class
class Comment
  # Now you can do your mocking
end

A sexier and cleaner way to do this is to use Module#class_eval:


Comment.class_eval do
  def is_spam?(permalink); false end
end

In the code above we’re calling a method on the Comment class and, as the Comment constant does not yet exist in Ruby’s ObjectSpace (Ruby throws a NameError), Rails will go and search the load path and require your Comment model for you.

So how to hook this into your config files? Why, config.after_initialize of course!

(if you haven’t heard about after_initialize I highly recommend you read my last article on the Rails initialisation process)

In my case, I just added the following to config/environments/development.rb:


config.after_initialize do
  Comment.class_eval do
    def is_spam?(permalink); false end
  end
end

So there you go: super-simple mocking, using nothing but standard Ruby.

Archived comments

Comments were previously allowed on articles. Though no new comments are being accepted you can see the old comments below.

  1. Voloshin Ruslan

    thank you for the simple example

Thoughts

toolmantim

I’m Tim Lucas, a user experience developer currently in Sydney Australia.

I occasionally write, snap photos, present on various technical topics, tweet my going-ons, share teh codes and post tidbits to the scrapbook.

Most recently I published Simplifying ticket sales on sydneyoperahouse.com (February 16, 2010)

Work with me via Agency Rainford, or shoot an email to and say hello.

Powered by procrastination