Building a modern CRM in Ruby on Rails — Part 1

This is the first of a series of tutorial on building a Customer Relationship Management application using Ruby on Rails.

Catalin Ionescu
Nov 13, 2020 · 6 min read
Image for post
Image for post
Building a modern CRM in Ruby on Rails


While there are some obvious champions in this field (yes, of course, I’m talking about Salesforce), some businesses don’t want something as complex and expensive as that.

I’ve also noticed a trend recently, where people prefer using niche CRMs rather than generic solutions. The owner of a beauty clinic would rather use a CRM where the customer is called a client, where they can create a list of services and track their current product stocks. Any feature on top of it (like Referral tracking or Lead funnels) would be extraneous and likely require the owner to pay much more than she needs to.

This environment creates a lot of opportunities for engineers to build side hustles for very niche audiences. What is more, if you are a Ruby on Rails engineer (or if you are just willing to learn), there is a very low barrier to building your first CRM.


We will build a CRM for a salon owner to manage her clients and appointments. Hence, we’ll need a Client model, an Employee model, a Service model (to record information about the services offered by the salon) and an appointments model.


  1. Part 2: Set up Invoker, Integrate Webpacker with Active Admin, Use a modern theme for Active Admin


  • Set up our environment (Ruby and Ruby on Rails)
  • Create a Rails 6 application
  • Add ActiveAdmin
  • Create the Clients model
  • Add an ActiveAdmin resource for Clients

Installing Ruby and Rails

We will use Ruby 2.7.1 (latest release as of September 2020) and manage our Ruby versions using rbenv (link to install rbenv).

$ rbenv install 2.7.1

As of September 2020, the latest Rails version is

$ gem install rails -v
$ rails new my-crm —database=postgresql —webpack=react
# Create the development and test databases
$ bin/rails db:create

Adding Active Admin

Add the gem to your Gemfile

gem ‘activeadmin’, ‘~> 2.7.0’

Then run:

$ bundle
$ bin/rails generate active_admin:install --skip-users
$ bin/rails db:migrate

The generator did a lot of things for us so let’s unpack them:

      create  config/initializers/active_admin.rb
create app/admin
create app/admin/dashboard.rb
route ActiveAdmin.routes(self)
generate active_admin:assets
rails generate active_admin:assets
create app/assets/javascripts/active_admin.js
create app/assets/stylesheets/active_admin.scss
create db/migrate/20200905183_create_active_admin_comments.rb
  • It created an initializer in config/initializers/active_admin.rb where we can find the default settings for ActiveAdmin. We don’t need to change anything there yet
  • It created the app/admin folder where we will create all of the pages for our CRM — each Active Admin resource defines all the actions performed on that resource. We will create our first action later in app/admin/clients.rb. For starters, we will only use the basic CRUD actions (Create, Read, Update, Delete), but could add custom actions in the future — like sending a birthday card via e-mail. All of these actions will be defined in the Clients resource.
  • The generator also appended ActiveAdmin.routes(self) to config/routes.rb. This will automatically generate routes for all of the actions we define in our resources.
  • The active_admin:assets generator will create a JS and a CSS file we will use down the line to style our CRM
  • Finally, the generator creates a table for the Comments resource — this is a default in ActiveAdmin (one we can turn off from the initializer if we want — look for config.comments = false and change it to true). Comments are a great way of allowing your admins to leave notes on each resource without having to build a custom tool for that.

At this point, we should have a barebones Rails application. You need to start the server and the webpacker process (to build your assets) using these two commands (in two different terminal windows).

# Window 1
$ bin/rails s
# Window 2
$ bin/webpack-dev-server
Image for post
Image for post
localhost:3000 displaying the default Rails root

If you navigate to localhost:3000/admin, you should see the default ActiveAdmin dashboard.

Image for post
Image for post
localhost:3000/admin displaying the default Active Admin dashboard

Adding the Client model

$ bin/rails g model Client name:string phone_number:string email:string birthday:date

The generator does a couple of great things for us:

invoke  active_record
create db/migrate/20201024130139_create_clients.rb
create app/models/client.rb
invoke test_unit
create test/models/client_test.rb
create test/fixtures/clients.yml

Let’s break it down:

  • It creates a migration in the db/migrate folder.
  • It creates a model file. The model file might be hard to digest in this state, so you might want to take a look at my other tutorial on using the Annotate Gem.
  • It generates a fixture and a model spec. We’ll come back to these in the next part when we’ll implement the model spec using fixtures.

Ensure you run db:migrate afterwards to create the tables:

$ bin/rails db:migrate

Adding the Client resource in Active Admin

$ bin/rails generate active_admin:resource Client
Image for post
Image for post
Active Admin Navbar has a link to the Clients resource

If you refresh the browser, you will notice that the navbar has a link to the Clients resources. Pretty neat since we didn’t have to add a single line of code for that.

Take a look atapp/admin/clients.rb. You’ll notice that the file is mostly empty:

ActiveAdmin.register Client do  # See permitted parameters documentation:  #  # Uncomment all parameters which should be permitted for assignment  # permit_params :name, :phone_number, :email, :birthdayend

Before we can create a Client, we need to set up strong params. Edit app/admin/clients.rb and uncomment the permit_params. Let’s type in the params we want to permit:

permit_params :name, :phone_number, :email, :birthday

If you are unsure, take a look at this commit which implements this change. This is the form generated by default.

Image for post
Image for post


I made a release in git for the work we’ve done so far so you can compare with your results.

In the next chapter, we’ll set up Invoker, use Webpacker for assets and add a great-looking theme to Active Admin.

Modern Rails

Learn how to build modern Ruby on Rails applications

Catalin Ionescu

Written by

Ruby on Rails Software Engineer Consultant. Bristol University alumnus. Founder of Organisely. Author of Modern Rails.

Modern Rails

We’ll delve into what’s needed to build a Modern Rails application in 2020

Catalin Ionescu

Written by

Ruby on Rails Software Engineer Consultant. Bristol University alumnus. Founder of Organisely. Author of Modern Rails.

Modern Rails

We’ll delve into what’s needed to build a Modern Rails application in 2020

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store