Thursday, April 9, 2009

Rails ActiveRecord update and Ruby Observable update in conflict?

In a recent project I've tried using Ruby's Observable module (from the Ruby standard library).I've created a Donation class (the subject) and a DonationObserver (the observer). 

As per the definition DonationObserver is supposed to provide a method called update to participate in the observer pattern. In my case, it had 2 parameters.

I also wanted to save these observers into the database and load them on demand. Hence, DonationObserver extended ActiveRecord::Base (it was one of my model classes).

Everytime an attempt is made to update (into the database) the runtime resolves that call to the update method defined for the purpose of the Observer pattern (in my DonationObserver). This produces a large stack trace complaining "wrong number of arguments (0 for 2)" and pointing all the way to line 2483 in base.rb where it says:
def create_or_update
raise ReadOnlyRecord if readonly?
result = new_record? ? create : update # line 2483 in base.rb
result != false
end
In other words, it appears that being the observer and an active record instance simply will not work together without some hacks. Perhaps I'd need to override the Observable's notify_observer method and call a different method in the target observer from the default update.

Am I missing something?

[Update]
Well, a quick and dirty way out of this is to just simply override the add_observer and notify_observers methods from observer.rb. You'll need to change the:
unless observer.respond_to? :update
to checking for any other method you're going to use:
unless observer.respond_to? :update_observer
Similarly, change the notify_observers from:
for i in @observer_peers.dup
i.update(*arg)
end
to:
for i in @observer_peers.dup
i.update_observer(*arg)
end
And finally, the observer class (DonationObserver) would get a new method called update_observer(...) with some appropriate arguments.