Observer and Singleton design patterns in Ruby

This is my first article in http://railsmagazine.com, it was published in issue 3, so basically I’m just republishing it here again.

Observer and singleton are two common design patterns that a programmer should be familiar with, however what made me write about them, is that both are there out of the box for you to use in ruby.
So let’s have a look at both and see how ruby help you use them directly:

Observer Design Pattern

According to Wikipedia:

The observer pattern (sometimes known as publish/subscribe) is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems.

So how does ruby help you implementing this design pattern? Well, the answer is by mixing the observable module into your subject (observed object).
Let’s take an example, let’s suppose we have a banking mechanism that notifies the user by several ways upon withdrawal operations that leaves the account with balance less or equal to $0.5.
If we look deeply at this problem, we can qualify it as a good candidate for observer design pattern, where the bank account is our subject and the notification system as the observer.
Here is a code snippet for this problem and it’s solution:

So to user ruby observer lib we have to implement four things:
1- Require the ‘observer’ lib and include it inside the subject (observed) class.
2- Declare the object to be ‘changed’ and then notify the observers when needed – just like we did in ‘withdraw’ method.
3- Declare all needed observers objects that will observe the subject.
4- Each observer must implement an ‘update’ method that will be called by the subject.

Observers in Rails

You can find observers in rails when using ActiveRecord, it’s a way to take out all ActiveRecord callbacks out of the model, for example a one would do this:

A neater solution is to use Observers:

You can generate the previous observer using the following command:

You still can have observers that map to models that don’t match with the observer name using the ‘observe’ class method, you also can observe multiple models using the same method:

Finally don’t forget to add the following line inside config/environment.rb to define observers:

Singleton Design Pattern

According to Wikipedia:

In software engineering, the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object. (This concept is also sometimes generalized to restrict the instance to a specific number of objects – for example, we can restrict the number of instances to five objects.) This is useful when exactly one object is needed to coordinate actions across the system.

The singleton design pattern is used to have one instance of some class, typically there are many places where you might want to do so, just like having one database connection, one LDAP connection, one logger instance or even one configuration object for your application.
In ruby you can use the singleton module to have the job done for you, let’s take ‘application configuration’ as an example and check how we can use ruby to do the job:

So what does ruby do when you include the singleton method inside your class?
1- It makes the ‘new’ method private and so you can’t use it.
2- It adds a class method called instance that instantiates only one instance of the class.
So to use ruby singleton module you need two things:
1- Require the lib ‘singleton’ then include it inside the desired
class.
2- Use the ‘instance’ method to get the instance you need.

14 Replies to “Observer and Singleton design patterns in Ruby”

  1. Hello,

    I intend to create an Observes to observe some models that dispatch specific actions. Depends on the current model, one of the actions is dispatched. To know which action must be dispatched, many business rules should be certified, making my Observer very complex.
    Do you recommend to create this kind of Observer?

    thanks, guilherme maranhão

  2. @gui_maranhao, Rails Observers don’t work with controller actions, instead with model callbacks. Anyway I prefer observers for callbacks to normal model methods, specially when the code base becomes complex.

  3. Thanks,

    When I mentioned “actions” I did not mean controller’s actions, I meant inputs in my db to register loggs and things like that, sorry.
    I also use them as callbacks to model methods. I’ve answered my question!

    thanks again

  4. In my last post I wrote: “I’ve answered my question!”. SORRY, it should have been: “YOU’ve answered my question!”

  5. No worries, always try to make your code readable by breaking it to parts that makes sense. Observers are cool place for callbacks and complex code related to them.

  6. Khelll,

    In order to reduce the complexity of my observers, I would like to know if it is possible for my Observer to observe specific methods (not just the models) of my models, like this:
    def after_

    end

    Thanks, guilherme

  7. I really dig your blog, and the “cool Ruby questions” series specifically.

    Sorry if that sounds like total dumbass nitpicking, but a few whitespaces in the first code sample won’t hurt IMO:


    @owner, @balance = owner, amount
    ...
    @balance -= amount if (@balance - amount) > 0

  8. Hi, I want to know how to linkthe observer of one model to another model in Rails?
    I would also like to know how to pass random variables between two models.
    Thanks
    P.S. I am a novice on Ruby on Rails and I have a lot of small doubts. Your help would be appreciated.

  9. Bad example with BankAccount. Now, the BankAccount class depends on EmailNotifier, SMSNotifier. It cannot function unless those classes exist. You’ve created tight-coupled-ness.

  10. But black wild, short satisfaction! Yes, size is also just. And just a little taste of the chain a bit slippery, but overall very satisfied. Good, very good, very fond of, and concerned about this bag for a long time, and finally succeed are only wishful heart, happy good, very small, very soft leather, with the use of say, well, continue to buy, I hope, as I hope. Yes, customer rain very patient, very good, bags are also good, quality is also very good, next time come! Yes, the style is very beautiful, quality feel good, work is not rough, a lot better than before that section, it is worth a good, enjoyed it. Thank stores to send a small gift friends.
    oakley gascan cerakote sunglasses http://vlvl.vn/FallGlass.aspx?bzBrMGUwYzAwOTk1MjNiMDU.html

Leave a Reply

Your email address will not be published. Required fields are marked *