Postlaunch

Leaving My CMS In The Cloud

Every time I work on a large Rails app, the mass of the code repository grows faster than it needs to, as branding and other non-code assets change in the "/public" directory. Frequently, a non-trivial amount of developer time gets consumed with accepting and committing updates for "/public" from project participants who don't speak Git.
One obvious solution is to embed and train everybody on a Rails-based CMS, and store those assets in a database, S3, or other location external to /public. Each time I've tried this, it's resulted in a lot of development work, since feature-rich Rails CMS have a heavy footprint and compatibility issues exert a strong influence over how I can build the application.
We've seen and/or walked other paths, too, like building needed management capabilities directly into the app, and using JRuby to bridge the Rails app into an enterprise environment with cooperatively managed databases. These involve a lot of project-specific investment.
Finally, I'm doing something I'm excited about with the next update to the IUCN Red List; I'm leaving the CMS in the cloud.
With a fallback route (at the bottom of routes.rb):
match '*url' => 'postlaunch#content'
any request not already responded to by Rails will be passed to a controller which knows about a remote CMS backing the system. In some cases, that means pulling an asset from the CMS in realtime using Typhoeus (or from the locally memcached representation of such content), or else to redirect to a content distribution network - CloudFront in my case - where the asset can be retrieved more efficiently.
Since here I'm using our PostLaunch CMS, which happens to already be pretty good about providing a REST API for layout templates and other branding materials, I take advantage of that too. My application layout fetches the current page template from the CMS (or memcache, etc.) and injects the yield of the current view -- and any other variables I set -- into it using Nokogiri.
That's actually a huge win for me, not having to track a big ERB or HAML version of the current HTML branding of the site. It's nice having a tiny application.html.haml like this:
- inject_into_cms_layout |
 'head' => (render :partial => 'layouts/headers'), |
 '#copy' => yield
!= apply_cms_layout
With only a little optimization (say 5% of a possible 100%), the performance is already great, and my application slug size and Git repository are staying super small, which gives me effectively instant redeploys on Heroku. The content managers can march on with browser-based or file-share-based tools, in blissful ignorance of Git and Heroku deployment.
A lot more work will come on this approach in the coming month, and I'll probably gemify the PostLaunch-specific controller for easy re-use in other projects with all the appropriate performance tuning already done. So far, though, the initial experiments are working out great, and I'm super happy with a CMS+webapp integration for the first time ... ever.
Recent insights