Which CMS you use in Rails? Try ComfortableMexicanSofa

Billy Cheng
The Startup
Published in
7 min readJun 17, 2020

I have done numerous web-based projects. Whenever it is customer facing, most of them requires some kind of customized content that needs to be changed from time to time. For simple pages, you may just be tempted to create a few using pages_controller to handle the static pages. For more complicated and required more frequently changed contents, a proper CMS is always a necessity.

I have been in love with LocomotiveCMS for sometime, but recently I have been using ComfortableMexicanSofa for several projects. I am going to show you how to integrate this to your existing projects and a few things that you need to do to setup your first CMS-backed site.

  • Installation and Setup
  • Navigation Menu
  • Customized Contents in Admin

Installation and Setup

The installation is very straightforward even to your existing application.

  1. Add gem definition to your Gemfile:
gem ”comfortable_mexican_sofa”, ”~> 2.0.0”

2. Then from the Rails project’s root:

$ bundle install
$ rails g comfy:cms
$ rails db:migrate

Once you are done with it, you will notice a few things:

Your routes.rb is updated with these 2 lines.

comfy_route :cms_admin, path: ”/admin”
comfy_route :cms, path: ”/“

If you are installing in an existing, make sure you cut these lines and paste to the end of the routes.rb . This ensures the CMS engine is probably routing your request.

By default, the route to the admin is http://localhost:3000/admin as you can see the definitioncomfy_route :cms_admin, path: ”/admin” in routes.rb. The Admin credentials are defaulted to be username: username and password: password. You could change that in /config/initializers/comfortable_mexican_sofa.rb.

Once you are done with all these, it’s time to log in to the Admin and create your first site.

Create a site

Setting up your first site is simple. In the side menu, go to “Site”, then input the label, identifier, hostname, path and select the default language of your site.

Label is the name of the site;

Identifier is the unique ID of your site, later on if you want to look up your site using the model, this is the identifier you use.

Hostname will match your domain name of the site.

Path is where you want to map to this CMS. In my case, I would like to map to to the root of the domain

Language is just your primary language of the site.

That is all you need to create a site.

Create a Layout

Next we will create a few pages and show you how you can create a navigation menu based the pages.

A layout is like a template which you could reuse by many pages that you create. For example, you could create a layout for your Blog List and different layouts for your Blog posts.

The App Layout will be looking for layout file in your app/views/layouts folder. I created a cms.html.erb for demonstration. You can see there are some javascripts in the sample layout. You can ignore those. However if you are intersted in Semantic UI / Fomantic UI, you can refer to my previous article.

<!DOCTYPE html>
<html>
<head>
<%= render partial: "shared/head" %>
</head>
<body>
<!-- Following Menu -->
<%= render partial: "shared/menu" %>
<!-- Sidebar Menu -->
<%= render partial: "shared/sidebar_menu" %>

<div class="pusher">
<!-- Page Contents -->
<%= yield %>
<!-- End Page Contents -->
<%= render partial: "shared/footer" %>
</div>

<script>
$(document).ready(function() {
// fix menu when passed
$('.masthead')
.visibility({
once: false,
onBottomPassed: function() {
$('.fixed.menu').transition('fade in');
},
onBottomPassedReverse: function() {
$('.fixed.menu').transition('fade out');
}
});
// create sidebar and attach to menu open
$('.ui.sidebar')
.sidebar('attach events', '.toc.item');

});
</script>

<%= yield :foot_js %>
</body>
</html>

Then you can create a layout like the following. Inside the Content section is where the <%= yield %> belongs to.

Layout sample and below is the sample code inside the Content section
// Sample layout code<div class="ui vertical masthead center aligned segment" style="background-image: url('{{ cms:file background_image, as: url }}')">
{{ cms:partial "shared/masthead_menu" }}
<div class="ui text container">
<h1 class="ui header">{{ cms:text big_title }}</h1>
<h2>{{ cms:text second_title }}</h2>
<div class="ui huge primary button">{{ cms:text call_to_action }} <i class="right arrow icon"></i></div>
</div>
</div>
<div class="ui vertical stripe segment">
<div class="ui middle aligned stackable grid container">
<div class="row">
<div class="eight wide column">
<h3 class="ui header">We Help Companies and Companions</h3>
<p>We can give your company superpowers to do things that they never thought possible. Let us delight your customers and empower your needs...through pure data analytics.</p>
<h3 class="ui header">We Make Bananas That Can Dance</h3>
<p>Yes that's right, you thought it was the stuff of dreams, but even bananas can be bioengineered.</p>
</div>
<div class="six wide right floated column">
{{ cms:file first_picture, as: image, class: "ui large bordered rounded image" }}
</div>
</div>
<div class="row">
<div class="center aligned column">
<a class="ui huge button">Check Them Out</a>
</div>
</div>
</div>
</div>
{{cms:wysiwyg content}}

There are several points you notice from the sample code above. Those lines that are bold are the tags used by the ComfortableMexicanSofa engine and the rest are normal HTML code. Once you created a new page based on this layout, you will know what is happening.

HTML output from the sample page
New page based on Landing Page layout

Now you can relate to what you have defined. Background image is linked to the cms:file background_image, as: url, big title, second title and call to action are related to the text field cms:text. The CMS engine comes with a rich editor, Redactor. You can easily define one with cms:wysiwyg :content. The rich editor comes with all the necessary features to compose your rich content. One tag you have noticed is the cms:partial "shared/masthead_menu". This tag is actually same as render partial: "shared/masthead_menu" in your regular Rails view. In this case, you are integrating any partials in the Rails application to the CMS layout.

There are a few more tags that are defined by the CMS engine. You could further refer to the documentation of the content tags:

After you have created several of your pages, you may want to dynamically create a navigation menu for your website. In the next section, we are going to show you how to build one.

Navigation Menu

The ComfortableMexicanSofa comes with several global variables, one of them is @cms_site. You can use this to navigate the pages of your site. Below is how I defined mine inside shared/menu.html.erb.

// app/views/shared/menu.html.erb<div class="ui large top fixed hidden menu">
<div class="ui container">
<%= render partial: "shared/main_menu_items" %>
<div class="right menu">
<% if current_user %>
<div class="ui right dropdown item">
<a class="ui basic image large label"><%= image_tag "mark.png" %> <%= current_user.full_name %></a>
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="settings.html"><i class="cogs icon"></i>Setting</a>
<div class="ui divider"></div>
<a class="item" href="login.html"><i class="address card outline icon"></i>My Profile</a>
<%= link_to(destroy_user_session_path, method: :delete, class: "item") do %>
<i class="sign out alternate icon"></i>Logout
<% end %>
</div>
</div>
<% else %>
<div class="item">
<%= link_to "Log in", new_user_session_path, class: "ui button" %>
</div>
<div class="item">
<%= link_to "Sign up", new_user_registration_path, class: "ui primary button" %>
</div>
<% end %>
</div>
</div>
</div>
// app/views/shared/main_menu_items.html.erb<% @cms_site = @cms_site.present? ? @cms_site : Comfy::Cms::Site.first %>
<% page = @cms_site.pages.root %>
<%= link_to page.label, page.url(relative: true), class: "item #{is_page_active?(page)}" %>
<% if current_user %>
<%= link_to "Dashboard", dashboard_home_index_path, class: "item" %>
<% end %>
<% @cms_site.pages.root.children.published.each do |page| %>
<%= link_to page.label, page.url(relative: true), class: "item #{is_page_active?(page)}" %>
<% end %>

Customized Contents in Admin

Once you start building your CMS site, you will find the need to integrate with your existing sites more. Like managing existing models of your site.

We are planning to have a beta sign up form in our Travel Plan website. We setup a form and people could input their email and get notified when the beta link is ready. This is easy and you must have built a million form like this on your Rails app. Now you want to see who has sign up in an admin area. ComfortableMexicanSofa comes with a Admin, so how could we leverage this and no need to have a separate one?

You could simply start with this commandrails g comfy:scaffold Notification email:string and it creates all the necessary files for you.

// New files
db/migrate/create_notification_xxxxxxxx.rb
app/models/notification.rb
app/controllers/admin/notifications_controller.rb
app/views/admin/notifications/
// Updated file
config/routes.rb
// Overridden from the CMS framework
app/views/comfy/admin/cms/partials/_navigation_inner.html.haml

All the new files generated are ready for action with CRUD action. You could try out and make small changes to suit your need. The ComfortableMexicanSofa is using Bootstrap in the Admin and by default all files are HAML. However if you are more familiar with ERB like I do, you could change them as you wish.

Have fun with your first website in ComfortableMexicanSofa. In my next article I will show you more advanced tips on customizing the ComfortableMexicanSofa Admin.

If you have other good suggestions on CMS on Rails, leave me your comments. See you next time!

Want to learn more advanced techniques on customizing ComfortableMexicanSofa CMS? I have written another article to show you a few tips.

--

--

Billy Cheng
The Startup

Share my tips and codes on my work with Ruby on Rails