Migrating off Active Record Observers


(Robin Ward) #1

Let’s discuss Observers.

(This PR by @zogstrip inspired this post.)

In Rails 4 they are moving Observer support into a plugin:
http://blog.remarkablelabs.com/2012/12/observers-gem-extraction-rails-4-countdown-to-2013

I personally am not a huge fan of observers as you end up with swabs of code that gets executed when events happen, and you don’t always know about them. They’re generally in another file than your model, but not always one named after it! (see notification observers observes tons of stuff.)

They also make our tests run slower when executing tons of side effects that we usually don’t care about.


I would like to migrate away from the observer pattern in our code base. I would even like to take it further and suggest that we replace most of our ActiveRecord callback stuff too.

We have tried out Service Classes in our code base, such as PostCreator and TopicView and I think they’ve been working quite well.

I think it might be a good idea to replace our observers with service classes. When you need the callbacks, you use the service class. When you don’t, just use the model directly. This should speed up our tests as tests of the model in isolation will never bother with the service class thing. The service class will be tested separately.

Thoughts?


(Tim Stone) #2

Hmm, can you kind of elaborate on how Service Classes replace the functionality of observers? It may just be my lack of Ruby knowledge, but since PostCreator is invoked directly, wouldn’t you have to make changes there to add new functionality?

That aside, since it would get rid of

swabs of code that gets executed when events happen, and you don’t always know about them

I’d be hugely in favour of this. Trying to sort through some of the notifications-related stuff was a pain.


(Robin Ward) #3

The idea of the Service class is you put the full lifecycle of callbacks in one class. So all those after_creates and such would be moved into the Service class. The service class uses the models in a lighter way.

Then we’d make sure the app uses the service class to do work rather than calling the models directly. But the unit tests can still happily test the models in isolation of the service class for their basic functionality, and this will be much faster as they won’t be calling all their after_create and after_save things.

Then we’d have a service class spec to test the the stuff that needs to happen when the service class is used. Those ones will be slower, but the cool thing is they won’t have to be called during every .save in our specs.


(Régis Hanol) #4

Plus, service classes make the code clearer by forcing developers to explicitly call them instead of relying on magical callbacks.


(Tim Stone) #5

I was more concerned from the perspective of plugin functionality, where you wouldn’t want to modify the Service class directly. Perhaps I’m putting the cart before the horse here though, and that’s something that will be addressed through a more robust plugin API once things are more stable.


(Sam Saffron) #6

I am all good to move off observers, they are a bit too magic for my liking.


(Jeff Atwood) #9

Did we ever do anything with this?


(Kane York) #10

Doesn’t seem like it to me – all the notification stuff still uses the observers as far as I can tell, which roadblocked me when I was trying to code up the notifications for lots of likes on a post, because I couldn’t figure out the code.


(Robin Ward) #11

We’ve migrated a lot of our code off observers but there’s still a bunch left. It’s a long process. Notification would be a good next one to tackle.