I didn't need a full blown CMS to meet the requirements for my current project, I just needed to make some paragraphs and static pages content manageable. The app uses restful-authentication to define user roles so I already had an Admin user type as part of the system, I've also used the tiny_mce gem for the content manageable fields. So how to add manageable content slots to a pretty standard Rails app.

I started with my model Content :

class Content < ActiveRecord::Base

  named_scope :latest_by_key, lambda { |key| {

    :conditions => ['contents.key = ? AND contents.status = ?', key, 'live'],

    :order => 'updated_at DESC'

  } }

end

 

Then a module called ContentManageable :

 

module ContentManageable

  def get_default_contents

    @contents = get_contents({})

  end

  def get_default_content

    @content = get_content({})

  end

  # TODO: call send against contents.first to retrieve a particular field?

  def get_contents(options)

    key = options[:key].nil? ? action_key : options[:key]

    all = options[:first] ? false : true

    contents = Content.latest_by_key(key)

    all ? contents : contents.first

  end

  def get_content(options)

    get_contents(options.merge!({:first => true}))

  end


  private

  def action_key

    "#{self.controller_name}_#{self.action_name}"

  end

end

 

 The idea here being that all content has a key and the default key is in the format controller_action

 In my ApplicationController I do this:

class ApplicationControllerActionController::Base

  include ContentManageable

 

  # Automatically retieve default content using the "controller_action" compound key.

  cattr_accessor :auto_content

  @@auto_content = false

  before_filter :get_default_content, :if => :auto_content

 

  ...

    def self.auto_content

    @@auto_content = true

  end

  ...

 

and this in contents_helper.rb:

 

module ContentsHelper


  def default_content

    cmsify(@content, nil) if defined? @content

  end


  def default_contents

    @contents if defined? @contents

  end


  def content_keys(key)

    keys = key.split '_'

    { :controller => keys[0], :action => keys[1] }

  end


  def cmsify(content, key)

    text = content.nil? ? '' : content.body

    if current_user and current_user.has_role? "admin"

      if content.nil?

        key = action_key if key.nil?

        text = "&nbsp;&nbsp;#{link_to '[add text]', new_admin_content_path({:key => key})}"

      else

        text += "&nbsp;&nbsp;#{link_to '[edit]', edit_admin_content_path(content)}"

      end

    end

    text

  end


  private

  def action_key

    "#{controller_name}_#{action_name}"

  end

end

 

So now any controller I want to auto content manage I can simple add auto_content at the top of the class and that controller will automatically look for content under the compound controller_action key, e.g. home_index. I place a <%= default_content %> in my view in the appropriate place to output the content body and as Admin either a link to edit this text or a link to add content to the slot.

(Should mention that admin/contents_controller.rb is a standard admin-role controller which handles standard CRUD for the content model.)

Then there's a whole bunch of other pages which are what you'd call static site pages, you know, Terms and Conditions, FAQ, About Us, that sorta stuff. For this I created another contents_controller.rb, this one is not an admin protected one, it simply has a show method:

 

class ContentsController < ApplicationController

  def show

    @content = get_content({:key => params[:id]})

  end

end

 

which means for an arbitrary key like about_us I can call the url http://localhost:3000/contents/about_us and my view will render the content body effectively giving me the ability to create any necessary static pages for the site. 

There are lots of bits that need tidying on but in less than a day I've got a simple way to handle paragraphs and complete pages which is a minor triumph for a relative Rails noob (I used shoulda_machinist_generator for the content scaffold so it's accompanied by unit and functional tests).  The code duplication of the action_key method is crap so I'll work that out sometime soon. 

 

blog comments powered by Disqus