Exit Rails-as-CMS, enter "Seamus" 0

Posted by ferrisoxide
on Wednesday, December 02

Adios Rails-as-CMS

The vast majority of traffic that comes to this website is generated by interest in the Rails-as-CMS post made over a year ago. While the attention is appreciated, it feels like this particular meme has run its course – at least for me.

Gaspard Bucher’s post Is Rails a CMS? puts paid to the Rails-as-CMS argument for most CMS implementations. I don’t buy his argument completely – for instance, you lose as much if not more flexibility by adopting the constraints of Gaspard’s Xena, Radiant or any of the other Rails-based CMSs out there. But I get where he is coming from – in general you are probably going to be better off embracing an existing package and extending it to meet your own needs.

The Rails-as-CMS idea still holds some interest for me – and probably for a few other Rubyists – because it allows for experimenting outside of the general case. My own need for a suitable vehicle for publishing some of my writing online is very different to what most people are looking for in a CMS. I accept that, and I’ve probably going a bit further by dropping Rails altogether for This Purple World and moving to Sintra. The results at the moment are pretty uninspiring, but once I get a moment to clean it up and post a more recent version on Github you can probably expect to see a new “Sinatra-as-CMS” argument start to brew. :)

Hola Seamus

With Rails-as-CMS out of the way – or at least on hold – I’d like to focus my energies back on a project I began a long time ago. Seamus started out as an implementation of the Content Mangement Interoperability Services (CMIS) specification. CMIS is about as far away from CMS as you can possibly imagine, despite the common “C for content” in their respective acronyms. CMIS belongs to the world of Enterprise Content Management systems – an evolution of the document- and record-management systems of yore. There are plenty of players in this market, from IBM and Microsoft with their proprietary offerings across to open source providers like Nuxeo and Alfresco. Most of the big players – including Nuxeo and Alfresco – have signed up to support CMIS in their products.

With the original incarnation of Seamus I managed to get a very basic implementation of CMIS version 0.5 going but was stymied by (a) spending way too much time trying to get my head around the way CMIS uses the Atom Publishing Protocol and REST and (b) having nothing real to wrap the system around.

I’m avoiding the hitting the same problems with Atom PP this time around by effectively ignoring the CMIS service model – instead using its domain model as inspiration and assuming that exposing the the system via a Atom/REST or SOAP interface should be relatively trivial, providing I stay close to the specification’s domain model.

The new implementation of Seamus will attempt to stay “real” by concentrating on a single problem domain – specifically the area of requirements management. Requirements are documents like any other – they have workflows associated with them, need to be maintained, versioned, distributed and so forth in a controlled manner. I’m imagining bootstrapping Seamus by using it to maintain its own requirements, thereby proving the system and creating a useful document set at the same time. And if Seamus can be used to satisfactorily manage requirements it may very well be extended to handle other types of documents.

I won’t be writing a single line of code until I have a clear baseline set of requirements ready. I know – a very “enterprisey” approach, but one I hope will pay off. I don’t have any high hopes for Seamus, other than what I expect to learn along the way. But it’s going to be an interesting journey, I hope.

This Purple World 0

Posted by ferrisoxide
on Thursday, June 18

Hey folks

Another proto-novel is now online. I’ve been loathe to put this one up for a couple of reasons. When I read the first few pages of this out at a writer’s group meeting years ago you could have heard a pin drop. Eventually a little old lady piped up with “it made me feel sick”. At the coffee break she later said “I guess you were trying to make me feel sick, so I guess it works as a piece of writing” – which I think was terribly nice of her to say.

I’m not convinced that it does work, but it’s out there now and we’ll see how it progresses. I didn’t want it to be the first piece I put up because I didn’t want the content to distract from what I’m trying to achieve in terms of using Rails as a content management system.

Keeping in with the idea that Rails is a language for expressing web sites, I’ve had to extend the language with a helper. I got sick of typing <%= link_to 'next page', :action => 'next_page' %> – indeed as I said I would – so I built a simple helper to remove the repetition. So now each page ends with a <%= link_to_page 'next_page' %>. The convention is that text is the same as the action, with underscores replaced with spaces. I’ll be in trouble if the text varies from this, but it hasn’t so far and I can always fall back to the old link_to approach.

As with The Young Person’s Guide To Time Travel, the code is up on github. The website for the writing can be found here:

http://thispurpleworld.com:

And before you say it, yes I am a sick puppy.

Young Person's Guide: Page 2 0

Posted by ferrisoxide
on Wednesday, June 17

OK, time for that tricky second page.. the bane of all pretentious writerly types out there in the blagosphere (hello brothers and sisters).

I had a bit of fun trimming all the superfluous verbiage from the original – I’m sure there’s a simpler way of saying that. There’s the implicit irony of using the “Hemingway” layout – I’m keen to slim this so-called novel down as much as possible, let it travel light and fast. As it happens I’ve been reading ‘The Old Man and the Sea’. Terse? Ernest was a C coder!

Joking aside, I do actually want you to read this story and enjoy it – I’d like it to be a ‘page turner’, as much as an online novel can be. An interesting convention I’ve played with before is to use the last few words on a page as the link to the next. It’s the closest approximation to a page turning experience I can think of.. when you come to the end of the page the last phrase is the trigger for going to the next page.. the loading time the little mental breath you take when you turn the page..

The implementation is deadly simple:

He hadn't read a complete book in years, but was still interested in <%= link_to 'opening lines', :action=> 'opening_lines' %>.


I’m using a link_to but it may get converted into a helper method later. This style of navigation may become unwieldy past a few pages, but we’re not there yet. As you may have noticed, I’m deferring all the hard stuff until I actually know I need to worry about it.

OK, we’re a few hundred miles away from making a general purpose CMS. But the spec has changed.

Have a look, tell me if it works for you:

http://guidetotimetravel.com

Rails as CMS: The Young Person's Guide 0

Posted by ferrisoxide
on Tuesday, June 16

Hi reader

Well, seeing as most of the traffic to this site seems to be from people looking for ideas on how to use Rails as a CMS I’ve got this basic pointer:

http://www.browsercms.org/

It’s pretty sexy. I’m in no way affiliated with the project – and that’s probably a good thing. If you want to get a CMS up and running quickly and be able to administer it with a minimum of fuss, this could very well be the thing for you.

On the other hand, if you’re still keen to see how far we can take this concept that Rails is effectively a language for describing a web site then my little project may be of interest. Fair warning.. it’s a bit odd, and might get suspended at any point if work or other pressures come to bear. With that in mind, let me introduce you to:

The Young Person’s Guide To Time Travel

Back in my uni days I started writing a novel. I don’t think that’s particularly unusual – many of us started writing a novel in uni. Some of us, like my old mate Penni Russon actually went on and got a novel published, but I chose to take a more traditional path and squash any idea of a successful career in writing under the rest of the pile of unrealised dreams and ambitions.

A while ago I blew the dust off a few old CD-ROMs and had a good look at my old writing. None of it was going to set the world on fire, but there was the odd spark – so I decided to give it another crack. Getting published is less of an issue as just getting something out there, so publishing online is an option. Since talking to Corey Doctorow at the Melbourne Writer’s Festival a few years back I’ve been interested in how the Creative Commons model provides a mechanism for writers to get their content out there without screwing their audience. I also want to live in a world where there’s a more direct dialogue between content creators and consumers. Apologies for (a) the implicit lefto-pinko-free-as-in-freedom sentiment and (b) name-dropping. For what it’s worth, I thought Corey was a decent guy.. though like many Canadians he has a funny-shaped head.

OK, enough of the back-story. Here are my basic requirements for a content management system:

  • I don’t have time to learn a new tool.

Drupal, Radiant, etc may be great but it’s another “language” I have to grok. I understand and enjoy the conventions of Rails – that’s all I want to have to know. When it comes time to customise I don’t want to have to work around a different set of conventions or code.

  • I don’t have time .. period.

I work full-time, have a family and a million other things in my life. The CMS needs to get out of my way and let me write. Anything clunky or complex is useless.

  • The CMS must support my tool set.

The novel will get written in small increments, in a very ‘agile’ sense (release early, refactoring, etc). It’s very similar to how I might write code. I expect to be able to use text editors on my laptop, use version control systems, preview work locally, test it.. just like I would with an application. In my head, the novel is just a different kind of application.

Some of this was covered in the original ‘Ruby on Rails based CMS’ post from way back. I’ll be revisiting the points from that article as we go, though not right now. My immediate aim is just to get something up and running as quickly as possible – and the simplest thing I can possibly do is to create a new Rails app, create a controller for serving up pages and drop the opening page in.

You can see the code here:

http://github.com/ferrisoxide/guide_to_time_travel/tree/master

There’s plenty to do – I’ve been incredibly lazy and not bothered to secure or structure the code at all. That can come later. The objective was to get something live as quickly as possible. I nicked the Hemingway layout from Warpsire, though I’ll need to get it looking a bit neater. Getting the actual site up and running simply a matter of shelling in an running git clone. From go to whoa took maybe all of an hour, spread over a few days, with the first page available here:

http://guidetotimetravel.com/

One gotcha – Dreamhost’s Passenger setup doesn’t seem to use your local gems, so if you are wanting to use Rails 2.3.2 you need to install it into your local gem repo and run rake rails:freeze:gems. It’s quite odd, as rails -v will return the 2.3.2 version number if it’s installed but I’m guessing Passenger looks at the version of Rails in the official Dreamhost repo (v 2.2.2 at the time of writing). Makes sense.

All good. Now we come to the difficult part for all aspiring part-time novelists: the tricky second page. But that’s a whole new blog post. ‘Til next time…

Cheers Tom

Acts As Static Content

Posted by ferrisoxide
on Thursday, February 26

Part 2 of the articles on content management in Rails. This was originally written almost a year ago, when I was slightly dumber than I am now. Included for completeness, but I really want to take this in a different direction. I should pull my finger out but for now I’ll maintain the illusion of industriousness by throwing up old blog posts.

Continuing the general rant aimless musing about Rails as a CMS

At work we use a single controller to serve up static content. The graphic designer on our team prefers to work with .html files in the file system so we use the static content controller to serve up web pages directly from disk. The files are ERB files – so ’.rhtml’ but close enough to be familiar to our designer. He also gets the bonus of all those helper methods, including custom helpers we build to make his life easier.

This approach has several advantages over keeping content in the database, like Radiant and others CMSs do. Firstly, publishing is just a matter of copying files into a known view directory. Secondly, we keep all content files under version control, so we can determine exactly which version of the content is to go live and which versions we can roll back to. We use branching to manage concurrent development of new content and maintenance of existing content.

We end up with the same model of development applying to both content and application development. The ancillary benefit is that everyone ends up talking the same language and content development ends up being managed with the same rigour that we apply to coding. This breaks down barriers in communication, allows us to work closely with designers and generally makes for a more enjoyable day’s work.

I want to use a similar approach with some documents I’m deploying as part of a web app. The documents aren’t going to change much but I don’t want to have to try to bundle them into the database using migrations. Apart from the duplication (the content would exist in both migration code and the database) I don’t want to have to build a new migration each time I make small changes to the text. Managing changes in a version control system is simpler so the static content controller approach suits here.

I also want to be to reuse this idea elsewhere, so I’m going to write the controller code as a plugin. If the code looks familiar, it’s because I nicked the original idea from here.

acts_as_static_content.rb

module ActsAsStaticContent

  def self.included(base)
    base.extend(ClassMethods)
  end 

  module ClassMethods
    def acts_as_static_content
      include ActsAsStaticContent::InstanceMethods 
    end  
  end  

  module InstanceMethods

    def static 
      #SMELL: assumes the convention app/views/foo for FooController
      if template_exists? path = "#{self.controller_name}/#{params[:id].to_s}" 
        render :template => path
      elsif template_exists? path += "#{self.controller_name}/index" 
        render :template => path
      else
        # pass through to the global error page handler
       method_missing params[:path].to_s
      end
    end

    protected 

      def each_page
        template_root = "#{RAILS_ROOT}/app/views/#{self.controller_name}" 
        excluded_actions = ['.', '..'].concat(self.hidden_actions)

        Dir.foreach(template_root) do |action|
          if !excluded_actions.include? action
            template_path = "#{template_root}/#{action}" 
            yield action, template_path
          end      
        end
      end  

  end
end    

ActionController::Base.send(:include, ActsAsStaticContent)    

The module code is introduced into controllers like any acts_as_X feature.

class MyController &lt; ApplicationController

  acts_as_static_content

end

Any ERB files sitting in the /app/views/my folder will be available via the mixed in ‘static’ method. If we want this controller to serve up all static content by default we add this to the end of routes.rb:

map.connect '*id', :controller => 'my', :action=>'static'

Not much to it and as someone will ultimately point out you can serve up content like this with any controller methods – just drop any .rhtml file into a view folder and it behaves like an action anyway.

Putting aside any question of whether this sort of behaviour is actually desirable, the aim is to centralize the mechanism for managing content. The immediate value is in the ‘each_page’ method, as this can be used to add search features – not an explicit requirement of a CMS as per the previous post, but one my app will need and I suspect so will others.

I need to give the ‘static’ method a bit more smarts, but it’s a start. We’ve already ticked off one requirement – versioning – with a few more ready to be knocked down. This first cut will probably be unrecognizable after a few refactorings, but the only way to find out is to see what happens against a real app. So.. next post: eating my own dog food… through a straw.

Rails as CMS 4

Posted by ferrisoxide
on Tuesday, February 24
This is from my old site and judging by the traffic the main reason why I get any visitors. While it possibly needs a tidy up - and it exposes some of my naivety from back then - I'm putting it up so people don't get completely cheesed off when they go hunting for the old post.

Rails is a CMS

There are now quite a few content management systems written in Rails. The chief ones would seem to be Radiant and Mephisto-as-CMS but there are dozens – of varying styles and sizes. For a quick overview there is a decent starting point. Please note: this used to be up on wiki.rubyonrails.org, but the site seems to have been trashed. The link points to a local copy retrieved from Google Cache.

The idea of using a framework on top of Rails to build CMSs has never sat right with me. I think of Rails as a kind of meta-language for describing web sites – essentially a mechanism for describing how web content is to be produced and consumed. The restrictions imposed by its architecture are easy to work with and make good sense – I’m not convinced I need to take on additional constraints and other conventions just to leverage code in an existing CMS solution.

But I could be wrong..

An idea I’m curious about: what’s the least you can do to build a working content management system using Rails? Let’s kick off by establishing what’s meant by a “content management system”. Looking back at the “starting point” wiki page there is a list of what the author considers essential features of a CMS:

  • Create and edit via redcloth/etc from web
  • Access control lists
  • Full customization of layout and style
  • Pretty urls (no /node/2235133/)
  • Subpage Content items, may be referenced freely by multiple owners (graph not tree)
  • Staging
  • Versioning
  • Lives as a component in rails, can reference content in a way similar to render_component in views
  • Should produce W3C standard (x)HTML/CSS/Accessibility web site

There has to be more – and indeed there is more on the wiki page – but let’s go with that as a start and refine the spec as we go. What would we need to do to get Rails to cover these requirements without too much head messing?

Rails + Plugins = CMS

There are several plugins that seem to come almost standard these days, the acts_as_X functionality you use to deliver authorization, authentication, logging. The thing I love about Rails is that it doesn’t dictate what tools you should use – you just start with the basic framework and you add whatever you need with either your own code or what you find in gem- and plugin-land. What you use for authorization may not be what I use – though we can be pretty sure there’ll be a class called User in there somewhere that we can shape to our own evil (or good – whatever rocks your boat) ends.

The plugins model works – evident by the way that all the good CMSs end up replicating it via their own extension/plugin frameworks. But there’s a cost you have to pay taking on board someone else’s stack – someone choses a particular set of gems or plugins for example, so you’re stuck with potential incompatibilities with other code. Features are well rounded in some areas and not in others, so you miss out on stuff you want so you can have stuff you need (or need right now). A whole series of little steps and forks in the path that may lead you to commercial/personal/spiritual reward – or completely deplete you. I’m a shocker for picking the wrong horse (ask my long suffering co-workers), so I want to take on as little as possible lest anything turn out to be a dud.

It’s a question of how far you are wanting to go down the path with any vendor and it’s often a difficult exercise. Engaging with like-minded souls is extremely important, so don’t think I’m arguing against cooperation with other developers. Being involved in the open source community would have to be one of the best things to do to keep yourself honest and honed. But I am arguing for simplicity, for valuing code and for knowing what’s going on inside the systems you build. It’s a bit of journey.. so let’s push on.

Create and edit via redcloth/etc from web

RedCloth installs as a gem, as do most of ‘etc’ I imagine. Liquid Templates is another nice way to mark up your views. There’s no shortage of specialized template rendering gems/plugins in use in Rails apps – including existing CMSs.

Access control lists

What level of access do you want to manage? What other authentication technologies (LDPA, OpenID, so forth) do you need to work with? Again, there are a stack of plugins that can cover your needs here. Next..

Full customization of layout and style

Rails’ layouts and views do this out of the box.

Pretty urls

Make graves. Again, Rails does this via routes, restful resources and custom actions.

Subpage Content items

Partials?

Staging

Out of scope – set up a proper staging environment and use capistrano to manage it. And Rails does allow for multiple environments. It’s really dependent on how you run your shop, but Rails does explicitly help here so I’m giving it a tick.

Versioning

Use a version control system.

Lives as a component in rails

Crazy recursive argument brewing. Best leave that one alone.

Should produce W3C standard (x)HTML/CSS/Accessibility web site

No, you should produce standard HTML/CSS and be prepared to hand-craft the damn thing until it works on all browsers more or less the same way. It gets back to knowing what’s going on in your system. How often have you had a website not render in your preferred browser because some clown didn’t know there’s a world outside of InternetExplorer?

There are plenty of things that will make running a CMS on Rails easier. But the fundamentals don’t change between much web apps and Rails does the fundamentals well.

Managing Static Content

One thing any CMS has to do well is manage static content – by which I mean the bread and butter brochureware that makes up the bulk of the typical commercial website. Revisiting and extending our requirements:

  • Content must be searchable
  • Content must be versioned
  • Content must be able to be staged
  • Content must be easy to update

Managing static content is a central feature in a CMS. All the fancy dynamic stuff is going to live in your custom controllers and views, as it will live in the custom code of any site aiming to present a unique and/or useful user interface. Dividing the design of the CMS between features addressing frequently changing content and the relatively fixed aspects will allow me to put the dynamic parts of a CMS aside initially and concentrate on looking after the management of static content first.

The Plan

I’ve just realised I’ve said most of this before in an earlier post. Wups! Not only am I getting grumpier I’m getting forgetful. The last post sort of wandered about a bit without actually getting anywhere. I’m proposing this time around I take the outrageous step of building something that works. I’ll be borrowing some ideas from a similar system we use at work, but will be extending it along my own lines. Nothing will be particularly original – I’m not much of a coder – but I’m hoping it will be useful. And I’m kind of keen to pick up some knowledge along the way.

Next Post: The Static Content Controller