Posts by Ernesto Jiménez:

Event Management in Rails: Observers

All Rails developers use ActiveRecord callbacks. The use of these callbacks helps our models: validation, data manipulation, relational operations, automatic sending of emails…

When you start developing with Rails, all these operations I mentioned are normally done in the controller. However, as we begin to lighten our controllers we fatten up our models with more and more callbacks. This is a good thing but at times we end up with a load of callbacks in the model that have nothing to do with the model.

To extract all this disparate code which has nothing directly to do with the model, Rails gives us observers.

Inside Observers

In this post, we’ll see how Rails observers work. For this it’s necessary to know how they are used so, if you’ve never used them, you should take a look at the documentation :)

The Ruby Observable module

Ruby implements some common design patterns in its standard library. One such module is Observable.

The Observable module implements the Observer pattern, also known as Publish-Subscribe. In this pattern, an object (the publisher or source) informs a group of interested objects (the subscribers) when it’s state changes. To accomplish this, we are given a series of methods to register subscribers and to notify them of state changes.

Let’s see an example of the use of the Observable module:

require 'observer'

class SystemMonitor
  include Observable

  def run
    last_free_space = nil
    loop do
      free_space = Disk.free_space
      puts "Free disk space: #{free_space}MB"
      if free_space != last_free_space
        changed
        notify_observers(free_space)
        last_free_space = free_space
      end
      sleep(60)
    end
  end
end

class DiskMainteinance
  def initialize(limit)
    @limit = limit
  end

  def update(free_space)
    if free_space < @limit
      puts "-- Cleaning temp files. #{free_space}MB free"
    end
  end
end

class AlertLowSpace
  def initialize(limit, email)
    @limit = limit
    @email = email
  end

  def update(free_space)
    if free_space < @limit
      puts "-- Notifying to #{@email}. #{free_space}MB free"
    end
  end
end

monitor = SystemMonitor.new
monitor.add_observer(DiskMainteinance.new(700))
monitor.add_observer(AlertLowSpace.new(700, 'peter@example.com'))
monitor.add_observer(AlertLowSpace.new(600, 'john@example.com'))
monitor.run

I think the example is pretty easy to follow, but it’s best if I clarify some details :)

The Observable module defines a series of methods that you can look up in the module documentation. In our example we use three of these:

  • changed(state=true): the state of the object has changed.
  • notify_observers(*args): i f the state is true, invoke the update method of each subscriber with the same arguments.
  • add_observer(observer): register a new subscriber.

Lets see an execution example of the previous script:

Free disk space: 1011MB
Free disk space: 821MB
Free disk space: 880MB
Free disk space: 625MB
-- Cleaning temp files. 625MB free
-- Notifying to peter@example.com. 625MB free
Free disk space: 730MB
Free disk space: 570MB
-- Cleaning temp files. 570MB free
-- Notifying to peter@example.com. 570MB free
-- Notifying to john@example.com. 570MB free
Free disk space: 716MB
Free disk space: 841MB
Free disk space: 1016MB
ActiveRecord: Publisher and Subscriber

ActiveRecord has two classes involved in event management:

  • ActiveRecord::Base: includes the Observable module and notifies the subscribers of al events to which callbacks can be associated
  • ActiveRecord::Observer: the base class for all observers and defines the update method

When a model (i.e. a subclass of ActiveRecord::Base) changes its state it invokes, in addition to the callbacks in the class itself, the method notify_observers with the following arguments:

  • The name of the event: before_validation, after_save, after_destroy…
  • The ActiveRecord object

    As we’ve seen, upon invoking notify_observers in the model, update is invoked on all the observers subscribed to the model. In the rails observers, the update method will invoke – if it is defined – the method of the class that has the name of the event notified and will pass as argument the object that has changed its state.

    # Send observed_method(object) if the method exists.
    def update(observed_method, object) #:nodoc:
      send(observed_method, object) if respond_to?(observed_method)
    end
    Initialisation of observers in Rails

    Now we’ve seen how ActiveRecord::Base notifies observers of events. Nevertheless, we’ve not seen how observers subscribe (as I’m sure you know, via a call to the method add_observer in the module Observable).

    When the rails observers call add_observer the constructor of ActiveRecord::Observer is run:

    # Start observing the declared classes and their subclasses.
    def initialize
      Set.new(observed_classes + observed_subclasses).each { |klass| add_observer! klass }
    end

    However, as the documentation states, to use observers, we don’t instantiate objects but instead we configure them in the environment.rb file (config.activerecord.observers_). This is to delegate to Rails the responsibility for initialising the observers.

    We’re not going to look at when they’re initialised, but instead how.

    The ActiveRecord::Observer class follows the Singleton design pattern. This pattern guarantees that there will be at the most one instance of a class. To achieve this, the visibility of the constructor is changed to private and a method is defined which returns the single instance of the class.

    This pattern is also included in the standard Ruby library in the Singleton module. This module changes the visibility of the constructor and defines the instance method.

    Therefore, Rails uses the instance method to subscribe the observers to the corresponding models.

    Knowing this…

    Knowing these details about the implementation of the Publish-Subscribe pattern in ActiveRecord and their initialisation in Rails, we have the technical knowledge to develop our own observers.
    We found it necessary to develop our own observers in order to have a single class that subscribes to various models but attending to different events depending on the model.

    In the next post, we’ll make the most of what we’ve explained here to look in detail at our observers.

    Happy Hacking! :)

    By Ernesto Jiménez
    Saved in: Programming | 1 comment » | 3 March 2008

    Technical decisions in Tractis

    Choice of Framework: Rails and Java

    A while ago, we described our decision to use Ruby on Rails to develop Tractis and stated that we were happy to have chosen rails instead of Java. We also mentioned that, given the deficiencies of Ruby, we opted to employ Java Web Services for the digital signature back end.
    Back then we were very happy with our choice of rails and we still are. The framework has given us a lot of agility and it’s fun to work with. Anyone who follows the blog has seen that we even participate whenever possible at Rails events to show our satisfaction.

    So, what of the development we’ve done in Java?

    Re-reading that post, it sounds like we’re developing in Java because there was no other choice – that if we’d had the necessary Ruby libraries we wouldn’t have any Java code and we’d be even happier. With the appearance of JRuby there are those who ask us if we’d not rather run the application in JRuby on Rails and therefore have access to the Java libraries that we need, eliminating our need for web services.

    Without doubt, that decision was not just about frameworks but was also an application design choice.

    The design choice: web services architecture

    As we said, when we selected the framework, we also chose the architecture. We decided that we wanted to develop various specific applications other than one that encompassed everything, in the pure UNIX style.

    The truth is that, looking back, we’re very happy to have opted for a Rails front end but we’re also very happy to have chosen a web services architecture. So, just like when we discussed the advantages of choosing Rails, now we want to share with you the advantages of using web services.

    Another buzzword

    This type of architecture is fashionable and even has it’s own buzzword: SOA (Service-Oriented Architecture). So you can now have your SOA application, done in Rails with a lot of AJAX.

    If, on the contrary, you are like us and you are not motivated by buzzwords, read on ;)

    Quality

    As we said earlier, the idea to design smaller and more specific applications that make up a larger application follows the UNIX philosophy.

    If we stop and think about it, this is the philosophy that makes UNIX so powerful and one of the reasons why we like it so much. You have a load of specific programs: ls, grep, sed, awk… these programs do specific things but they do them very well.

    Working with specific applications that have to resolve a concrete problem, we can concentrate much better on the problem at hand. You might think that to achieve task isolation it would be enough to develop libraries instead of applications – and you would be right. Having said that, developing distinct applications connected by web services allows us to have a totally language, framework and deployment-agnostic architecture. If, in the future, there are better tools in C++ or .NET for the validation of signatures, we can migrate just this application without impacting the rest of the system. Developing specific applications we can employ the best tools in each case.

    In addition to the improved implementation quality, we have also discovered improvements at execution time – on one hand for scalability reasons which we’ll discuss in the next section, and on the other the flexibility to redeploy or deactivate a specific service without having to shut down the rest of the services.

    Scalability

    When we talk about scalability, we refer to scalability of technical resources as well as human resources. On the technical side, it’s very simple. At the start, you can have all the services on the same machine and if one becomes a bottleneck, you just move it to a dedicated machine. Additionally, if the service is share-nothing, you can deploy it on as many machines as you need to give a high level of service. This will be clear to anyone who works with Rails :-)

    On the human side, a service-based architecture allows us more room to scale our development, meaning we can move from managing a single larger team to assigning a smaller team per service. This way, as we grow and require more developers, it won’t be necessary to have a bigger and bigger team but rather a group of small, agile teams that are in charge of one or more services.

    In future posts

    In future posts we hope to talk in more detail about the our architecture, the services that compose it and what they are used for.
    Bye for now!

    By Ernesto Jiménez
    Saved in: Programming, Technology, Tractis | No comments » | 28 January 2008

    Spanish Rails Conference 2007

    Bit by bit I’m getting through my to-do list after the terrible flu that I caught in Madrid and now I have to write a bit about my impressions of the Conferencia Rails (Spanish Rails conference) this year :)

    If I had to sum it up in a single word, it would be ‘intense’: many presentations, conversations in the hallways and even a few nights out. Both days we started at 10am and ended up finishing at 4am. These types of events contradict the myth that computer people are introverted and boring. There was an excellent atmosphere with good humor and a lot of laughs.

    Regarding my presentations, the feedback was positive (though I owe some people beers for this!) and the experience was pretty good, so I’ve promised to prepare another one next year and to try and improve. The slides from the presentations are here:

    If you couldn’t attend this year…don’t miss Rails Conferencia 2008! If it’s anything like this year’s, you won’t be sorry :)

    See you at the next one!

    By Ernesto Jiménez
    Saved in: Conferences | No comments » | 12 December 2007

    Launch of ACME: Demo site for the Tractis API

    Last week we gave you a preview of the API we’re working on and talked about some of the services that it will offer:

    • User authentication via Digital Certificates.
    • Automated sending of personalised contracts.

    Now we want to talk about some of the things we have ready. However much documentation we write, the best way to understand the capabilities of the API is to see it in action so we’ve decided to create a fictitious company – “ACME” – whose web site (http://acme.tractis.com) will demonstrate everything you can do with the Tractis API.

    acme1.png

    ACME: Demo of sending personalised contracts to clients

    The first example we’ve put on the ACME web site demonstrates the “Contract Management System”. The Tractis API allows you to use this system to automate the creating and sending of totally personalized contracts to your clients. As you’ll see in the demo, with the API you can:

    • Personalize the subject and body of the email that the customer will receive
    • Personalize the instructions that appear at the top of the contract. This is useful for explaining the steps to follow to the customer (“review the contract and, if you agree with it, press the ‘Sign’ button at the end of it”, ask for additional information, record delivery periods, etc.
    • Select the template that will serve as the basis for the contract. You can choose from the example templates or log in and use the templates in your private library.
    • Fill in the variables in the template that you’re going to use. Logically this option is only available if the template used includes variables. In this demo, all the contracts sent share the same variables (e.g. Buyer Name = “John Smith”). Of course, with the API, you can personalize the variables in each contract.

    Details for “sellers”

    Your clients are yours:

    1. They don’t have to register with Tractis to sign a contract.
    2. They will receive a personalized e-mail with the message sender, subject and body that you decide.
    3. They will agree to contracts personalized with your corporate image (logo, colors, instructions).

    Details for “techies”

    We’re still expanding the API documentation but we can tell you a few things:

    • Access: initially the API will be accessible via REST. In the future, we’ll also allow SOAP access.
    • Format: The data format is XML. In the current demo, you can see a preview of the XML requests sent to Tractis. Shortly, you’ll be able to see the trace of API requests.

    Work on the API continues…what do you need?

    In Tractis we firmly believe that the business potential of the internet goes beyond promotion and communication. Now you can negotiate and sign contracts 100% online and with the necessary legal guarantees. The technology and legislation are available right now.

    If you believe that your company could take advantage of these types of services, don’t hesitate – get in contact with us. We’ll be thrilled to hear your ideas for using the Internet and digital signatures to speed up and increase your business.

    By Ernesto Jiménez
    Saved in: Announcements, Programming, Tractis | No comments » | 5 November 2007