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 ApplicationController < ActionController::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 = " #{link_to '[add text]', new_admin_content_path({:key => key})}"
else
text += " #{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