sobota, 5 maja 2012

Apotomo - API done right

During the wroc_love.rb conference I had the opportunity to speak with Nick Sutterer (the original author and maintainer of great Cells and Apotomo gems) and thank him for the architectural choices made for the libraries. He said that I should blog about and help spread the good word instead of just telling him about the things that I like. So, here I am writing this post and keeping my promise.

The architectural choices are not obvious when reading Apotomo tutorial and probably they don't bring so much to most users of the library. Nevertheless they were extremely important to me. If you are not familiar with apotomo, just jump to the official website and Apotomo tutorial to get an idea of how it works.

Here is a little example of what we used apotomo widgets for:

Conceptually in apotomo it all starts in a controller.

But that's a very simple and basic thing you can do with apotomo. It all becomes much more interesting when you realize that the proc used by has_widgets method is not executed once but instead every time there is a request going to the controller. It is executed in scope of controller instance using instance_eval instead of being executed once during class loading with class_eval. And that gives a lot more opportunities and flexibility.

In my project every user was given some roles (like Admin, Chef, Vice-Chef) and widgets belonged to those roles. UserRoles and RoleWidgets was dynamically stored and retrieved to/from database and the UI changed accordingly. Even such details like widget width (100% vs 50%), position (left vs right) and their order could be configured per every role on database.

So, what's the moral of the story ? Please try to design your API with flexibility in mind. It might be quite easy to achieve it if you create new object every time it is needed and use instance_eval instead of doing all the meta-programming once with class_eval when loading the class for the first time. And if you worry about performance, please don't. Many times the bigger possibilities out-stand the probably negligible performance hit.