# Character ## Rails Setup An example of admin implementation setup for [Rails](https://github.com/rails/rails) app that uses [Mongoid](https://github.com/mongoid/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](https://github.com/plataformatec/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: ```ruby 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: ```ruby 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: 1. Authentication is not required when running in development or testing environment; 2. Need to setup ```index``` view and ```admin``` layout to render admin app; 3. ```bootstrap_data``` is 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. ```ruby class Admin::DeviseOverrides::SessionsController < Devise::SessionsController layout 'admin' end ``` Admin app layout ```app/views/layouts/admin.html.erb```: ```erb Admin <%= csrf_meta_tags %> <%= stylesheet_link_tag :admin, media: "all" %> <%= yield %> ``` Admin index view ```app/views/admin/index.html.erb```: ```erb <% admin_email = Rails.env.production? ? current_admin.email : 'developer@example.com' %> <%= link_to 'Sign Out', destroy_admin_session_path, 'data-admin-email' => admin_email, method: :delete, style: 'display:none;', class: 'menu-logout' %> <%= javascript_include_tag :admin %> ``` New session view for devise ```app/views/admin/devise_overrides/sessions/new.html.erb```: ```erb

Sign In

<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> <% if alert %>

<%= alert.gsub('username', 'email').gsub('or sign up', '') %>

<% end %>
<%= f.input :email, required: true, autofocus: true %> <%= f.input :password, required: true %> <%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %>
<%= f.button :submit, "Sign In" %>
<% end %> ``` Now connect admin and devise in ```config/routes.rb``` with: ```ruby 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: ```coffee #= 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```: ```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```: ```scss .sign-in { margin: 2em; max-width: 18em; h2 { text-transform: uppercase; color: $black; } input { @include no-outline; } label { color: $black; } .input { margin-bottom: .75em; } .input input[type=checkbox] { margin-right: .5em; } .input input.email, .input input.password { float: right; margin: -2px 0 0; width: 12em; border: 0; border-bottom: 1px solid $contrastColor; } .input.boolean { margin-top: 1.25em; } .form-actions input { width: 100%; padding: 1em 2em; margin-top: .75em; color: $white; background-color: $positiveColor; border: 0; } } ``` **Third**: make sure admin assets are precompiled on production, include ```admin.js``` and ```admin.css``` in ```config/initializers/assets.rb```: ```ruby 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...