Character
Powerful responsive javascript CMS for apps.
Rails
An example of admin implementation setup for Rails app that uses Mongoid stack.
Gems
Add to following gems to Gemfile:
gem "devise"
gem "mongosteen"
gem "chr"
This example uses devise for admins authentication.
Admin authentication
Start with running devise generator:
rails generate devise:install
Setup Admin model with devise generator:
rails generate devise admin
Here is an example of basic app/models/admin.rb model that provides email/password authentication:
class Admin
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::SerializableId
devise :database_authenticatable,
:rememberable,
:authentication_keys => [ :email ]
## Database authenticatable
field :email, type: String, default: ""
field :encrypted_password, type: String, default: ""
## Rememberable
field :remember_created_at, type: Time
end
When models are ready, setup controllers, views and configure routes.
Base admin controller app/controllers/admin/base_controller.rb looks like this:
class Admin::BaseController < ActionController::Base
protect_from_forgery
if Rails.env.production?
before_action :authenticate_admin!
end
def index
render '/admin/index', layout: 'admin'
end
def bootstrap_data
render json: {}
end
end
Notes on code above:
- Authentication is not required when running in development or testing environment;
- Need to setup
indexview andadminlayout to render admin app; bootstrap_datais a placeholder for objects that might be required to be loaded when app starts.
Devise would require a custom SessionController implementation in app/controllers/admin/devise_overrides/session_controller.rb. SessionController sets admin layout to be used for devise views rendering and enables login by email (looks like workaround).
class Admin::DeviseOverrides::SessionsController < Devise::SessionsController
layout 'admin'
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) << :email
end
end
Admin app layout app/views/layouts/admin.html.erb:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<title>Admin</title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag :admin, media: "all" %>
<%= javascript_include_tag :admin %>
</head>
<%= yield %>
</html>
Admin index view app/views/admin/index.html.erb:
<body class='loading'>
<%= link_to 'Sign Out', destroy_admin_session_path, method: :delete, style: 'display:none;' %>
</body>
New session view for devise app/views/admin/devise_overrides/sessions/new.html.erb:
<body class='sign-in'>
<h2>Sign In</h2>
<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<% if alert %>
<p class="error"><%= alert.gsub('username', 'email').gsub('or sign up', '') %></p>
<% end %>
<div class="form-inputs">
<%= f.input :email, required: true, autofocus: true %>
<%= f.input :password, required: true %>
<%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %>
</div>
<div class="form-actions">
<%= f.button :submit, "Sign In" %>
</div>
<% end %>
</body>
Now connect admin and devise in config/routes.rb with:
devise_for :admins, path: "admin", controllers: { sessions: "admin/devise_overrides/sessions" }
namespace :admin do
get '/' => 'base#index'
get '/bootstrap.json' => 'base#bootstrap_data'
end
Character setup
Three pieces to be configured here.
First: create app/assets/javascripts/admin.coffee with empty modules configuration:
#= require jquery
#= require jquery_ujs
#= require chr
$ ->
$.get '/admin/bootstrap.json', (response) ->
config =
modules: {}
$('body').removeClass('loading')
chr.start(config)
# append signout button to the end of sidebar menu
$('a[data-method=delete]').appendTo(".sidebar .menu").show()
Second: create foundation for style customization in app/assets/stylesheets/admin.scss:
@charset "utf-8";
@import "normalize-rails";
@import "chr";
@import "admin/signin";
Last import in the code above is optional. But here is a default source for it as well app/assets/stylesheets/admin/chr/_signin.scss:
.sign-in {
font-size: 14px;
color: #555;
margin: 3em 0 0 3em;
h2 {
text-transform: uppercase;
font-size: 1em;
font-size: 16px;
color: $black;
margin-bottom: 1.5em;
}
p {
margin: -1.5em 0 2em;
color: $positiveColor;
}
.form-actions, .form-inputs {
max-width: 280px;
}
.input {
margin-bottom: 1.5em;
}
input.string, input.password {
float: right;
margin-top: -.45em;
padding: .25em .5em;
width: 13.5em;
}
label.boolean input {
margin-right: .25em;
}
.form-actions input {
width: 100%;
padding: 1em 2em;
background-color: $positiveColor;
border: 0;
color: $white;
}
}
Third: make sure admin assets are precompiled on production, include admin.js and admin.css in config/initializers/assets.rb:
Rails.application.config.assets.precompile += %w( admin.js admin.css )
At this point initial setup for admin app is finished and it could be accessed via: localhost:3000/admin.
Add models
To be continued...
Bootstrap data
Bootstrapped data configuration example with disabled item updates and pagination:
postsConfig = (data) ->
itemTitleField: 'title'
disableUpdateItems: true
objects: data.posts
arrayStore: new MongosteenArrayStore({
resource: 'post'
path: '/admin/posts'
sortBy: 'title'
pagination: false
})
formSchema:
title: { type: 'string' }
body: { type: 'text' }
disableUpdateItems — do not update items in the list while navigation, objects — provides initial (bootstrapped) array of objects to be added to the list, pagination — disable pagination for list. If attached as modules root list, you can access store data with: chr.modules.posts.arrayStore.data().
Character tastes better with:
- Mongosteen: An easy way to add restful actions for Mongoid models
- Inverter: An easy way to connect Rails templates content to Character CMS
- Loft: Media assets manager for Character CMS
License
Copyright © 2015 Slate Studio, LLC. Character is free software, and may be redistributed under the terms specified in the license.
About Slate Studio
Character is maintained and funded by Slate Studio, LLC. Tweet your questions or suggestions to @slatestudio and while you’re at it follow us too.
