Help Engine

A basic system to add help pages to a Rails application.

I often find myself tacking a simple help system on to rails apps. They are usually very simple, and allow users to add and modify the content. As I do it so often, I thought I’d bundle it all into a gem so that I can make the process even simpler.

Installation

First add the gem to the host app’s Gemfile:

gem 'help_engine'

Then mount the engine via config/routes.rb:

mount HelpEngine::Engine => "help"

Usage

Each help page has a unique slug that is used to generate unique meaningful urls. So if a help page is named “Foo Bar”, it will have a slug ‘foo-bar’ and the page’s url will be help/pages/foo-bar.

To add a link to a particular help page, use the slug to identify the page:

<%= link_to 'help on Foo Bar', help_engine.help_page_path('foo-bar') %>

To add a link to the help index:

<%= link_to 'Help', help_engine.root_path %>

On this page links are provided to each of the existing help pages, and there is also a link to create a new help page. See the Overriding Help Engine behaviour section below regarding added access control to help pages.

Content

Markdown is used to define the content of help pages. The mark down used is as defined here:

http://daringfireball.net/projects/markdown/basics

Markdown is used as it’s easy to create well styled content without having to sanitise users’ input.

Dummy app

A dummy app is provided as part of this engine (test/dummy). This provides an example of how the engine can be used.

Author

Each help_page has an author polymorphic relationship. So an user can be associated to a help_page with:

help_page.author = user

A has_many method can be added to an author class such as User, like this:

class User < ActiveRecord::Base

  has_many :help_pages, as: :author, class_name: 'HelpEngine::HelpPage'

  ...
end

To store an author’s identity on help page creation, the help pages controller will need to be overwritten.

Overriding Help Engine behaviour

Overriding controllers

As with most rails engines, you can override the Help Engine behaviour by adding matching objects in the host app. So for example, if you want to override how the HelpEngine::HelpPagesController behaves (to add access control for example), add your own controller code at the host app’s:

app/controllers/help_engine/help_pages_controller.rb

For example, if Devise is installed, you may do something like this (at app/controllers/help_engine/help_pages_controller):

class HelpEngine::HelpPagesController < ApplicationController

  before_action :authenticate_user!, except: [:index, :show]

  def create
    @help_page = HelpPage.new(help_page_params)
    @help_page.author = current_user

    if @help_page.save
      redirect_to @help_page, notice: 'Help page was successfully created.'
    else
      render :new
    end
  end

end

Overriding views

HelpEngine views can be overridden in the same way. For example, in the dummy app the help_engine layout has been overridden so that bootstrap styling can be applied to the help pages. see:

test/dummy/app/views/layouts/help_engine/application.html.erb

This change has also modified where the CSS for these pages reside. For example, the textarea styling for the help_page content in the dummy app is defined at:

test/dummy/assets/stylesheets/help_pages.css

Deletion and JavaScript

For the help page delete button to work, the JavaScript environment must be correctly set up in the host application. In the dummy app this is done by using the ‘jquery-rails’ gem and enabling jquery in the asset pipeline by adding these two lines to app/asserts/javascripts/application.js :

//= require jquery
//= require jquery_ujs

This could be fixed by setting up jquery in the engine, but having had problems in the past with rails engines’ jquery configuration clashing with the host app’s jquery configuration, I don’t think this is best practice. For those interested:

http://stackoverflow.com/questions/8788304/activeadmin-stops-my-jquery-working