New Rails Template

In this article we take a look at a more complete Rails template, to start a new Rails project. Why? With a custom template, you can start developing your project immediately already preconfigured with the gems, packages, and settings you like to use.

Credit

The inspiration for my custom template starts with Andy Leverenz's Kickoff template. There are a few other great resources as well.

Jumpstart Chris Oliver has put together a template called Jumpstart. This template creates a Boilerplate app that includes user accounts, admin interface, and Bootstrap styling.

Jumpstart Pro Chris also has a commercial product called Jumpstart Pro that bootstraps a full featured e-commerce application setup.

Template Features

TL;TR: The completed repository to the finished custom rails template if you would like to jump straight to the code.

Using a Template

First let's cover the basics of using a template. The rails new command offers many command option flags, and provides a flag to use a custom template:

rails new myapp -m /path/to/my/template.rb

I had written on this topic previously in Rails Boilerplate. When this command is executed, Rails will run the script, install and create the new app.

Now, to streamline this process you can create a dotfile in the root of your file system: .railsrc. Rails will look for this configuration file first. In our case this is a good start:

--database=postgresql
-T
-m /path/to/my/template.rb

So, we can start the new project: rails new myapp. Rails will use Postgres database, will not install a testing framework (more on this later), and use our template, without having to type the commands on the command line.

If at some time you wan to create a default Rails app, instead of your custom setup: rails new myapp --no-rc.

A Custom Template

If you start to look at the main template.rb in the codebase you will notice at the top of the file is a series of methods, and the business logic of calling these methods:

# Main setup
source_paths

add_gems

after_bundle do
  stop_spring
  add_testing
  add_active_storage
  add_users
  remove_app_css
  add_sidekiq
  add_foreman
  copy_templates
  add_tailwind
  add_fontawesome
  add_stimulus
  add_friendly_id
  copy_postcss_config
  add_stimulus_navbar

  # Migrate
  rails_command "db:create"
  rails_command "db:migrate"

  git :init
  git add: "."
  git commit: %Q{ -m "Initial commit" }

Basically, after the bundle install in completed the methods are executed, it creates the database, a migration is run, and then the first git commit is saved.

So, let's go over a few of the methods to show you the power of the API.

Add gems

The add_gem method does not install these gems, it only adds the gems to the Gemfile. If you examine the method you will notice we are setting up gems associated with users, setting up a testing environment, and Rubocop.

def add_gems
  gem "devise", "~> 4.7", ">= 4.7.2"
  gem "friendly_id", "~> 5.3"
  gem "image_processing"
  gem "sidekiq", "~> 6.1", ">= 6.1.1"
  gem "name_of_person", "~> 1.1", ">= 1.1.1"

  gem_group :development, :test do
    gem "database_cleaner"
    gem "factory_bot_rails", git: "http://github.com/thoughtbot/factory_bot_rails"
    gem "rspec-rails"
  end

  gem_group :development do
    gem "fuubar"
    gem "guard"
    gem "guard-rspec"
    gem "rubocop"
    gem "rubocop-rails", require: false
    gem "rubocop-rspec"
  end

  gem_group :test do
    gem 'simplecov', require: false
  end
end

NOTE: After your app is set up you will probably want to clean up your Gemfile. All the above gems and groups are added to the bottom of the Gemfile.

If you have been following my articles you know I have written about this Rails Testing Setup before.

Testing

I noted previously, in the .railsrc file, we did not install the default Rails testing environment. In the add_testing method we are setting up Rspec.

def add_testing
  generate "rspec:install"

  directory "spec", force: true

  run "rm -r test" if Dir.exist?("test")

  copy_file "config/webpacker.yml", force: true
  copy_file ".rspec", force: true
  copy_file ".rubocop.yml"
  copy_file ".simplecov"
  copy_file "Guardfile"
end

Remember, this method will run after bundle install, so we are only configuring the gems here. Since we are using a repository, instead of just a simple template file, we can copy preconfigured files and directories:

You can read more about the Template API at Railsguides.

Modifying Files

In the creating process we can also modify files. For instance, in the add_tailwind method:

append_to_file("app/javascript/packs/application.js", 'import "stylesheets/application"' + "\n")
  inject_into_file("./postcss.config.js",
                   "let tailwindcss = require('tailwindcss');\n", before: "module.exports")
  inject_into_file("./postcss.config.js", "\n    tailwindcss('./app/javascript/stylesheets/tailwind.config.js'),", after: "plugins: [")

In this case we can append_to_file an import. Also, we are injecting into a file at a specific point (before of after some text).

We can also inject at the end of a file a block of inserts:

inject_into_file 'app/javascript/controllers/index.js' do
<<~EOF
  // Import and register all TailwindCSS Components
  import { Dropdown, Modal, Tabs, Popover, Toggle } from "tailwindcss-stimulus-components"
  application.register('dropdown', Dropdown)
  application.register('modal', Modal)
  application.register('tabs', Tabs)
  application.register('popover', Popover)
  application.register('toggle', Toggle)
EOF
end

The Template API is fairly robust and offers a way to streamline the startup time of a new project. This is my personal setup. Clone the repository and give it a try, tweak it for your own, and if something doesn't work, open a PR.

Footnote

This has been fun. Leave a comment or send me a DM on Twitter.

Shameless Plug: If you work at a great company, and you are in the market for a Software Developer with a varied skill set and life experiences, send me a message on Twitter and check out my LinkedIn.