Thursday, April 12, 2007

Tips for Developing Mephisto Plugins with Liquid and Rails

When I was writing a contact form plugin for Mephisto, I had a lot of trouble finding documentation and ended up reading lots of code and experimenting. That was fun, but fairly slow, so I hope this post can save future plugin developers time, and help them avoid some of the gotchas I stumbled over.

Repository Directory Structure
At the most macro level, your repository needs to have a 'plugins' directory, and then a directory named after your plugin. Eg,
If this is not set up correctly, your plugin will not be able to be installed via 'ruby script/install plugin ' method.

Liquid Plugins Directory and Init.rb
As you probably know, Mephisto uses Liquid for page templates. Liquid can be extended with new tags/blocks. The way to do this in a plugin is to set up a 'mephisto/liquid' directory with your extensions in it. See example here. So that's great, but you also need to register it in init.rb. Here's the contact form's init.rb - check out the line about 'register_tag'.

Mephisto Plugin Class
Mephisto trunk now has a base class for plugins - Mephisto::Plugin. Inheriting from this allows you to set up routes to brand new controllers you create. See contact form example here. This opens the door to writing Mephisto plugins which do postback and processing. It is also possible to add in tabs and forms in the administration interface. Rick's feedback plugin shows how to do this.

Using Liquid Templates from Your Plugin
One of the trickiest bits was getting the plug-in controller to render a liquid template. This is important if you want your additions to Mephisto to have the same layout and colours as the rest of the site. The way I'll outline below works fine, but it is not ideal. Hopefully there is a better way to do this (eg, some sort of Liquid API for Mephisto plugins).. if you know how a better way, please let me know!

I had my plugin controller inherit from the Mephisto ApplicationController to gain access to the method 'render_liquid_template_for'. You can see the code here. However, this led to thorny problems where the plug-in classes were getting loaded only once when the server started, but Mephisto (and the ApplicationController) were getting reloaded for every request. First request worked fine, but nasty errors were spat out on the second and subsequent requests. To resolve this, I removed the plug-in from the 'load_once_paths'. You can see how to do this in the init.rb.

Models, Views & Controllers Directories and Init.rb
Okay, this is open to personal taste. I like to have similar directories in my plugin to a normal app. Eg, separate directories for controllers, model, etc. This causes a bit more work, as you need to add the extra directories to various global path variables. For an example of how to do this, take a look at 'models_path' and 'controllers_path' in this init.rb and the physical directory structure of the contact form's lib directory.