Setting up a project with Ruby 3 + Rails 7.0.0.alpha2

#Ruby#Rails#Minitest#Postgres#Rbenv#Sass#Slim

Rails 7 brings Hotwire to be a framework default when a new project is created. Having it pre-configured during the project creation itself (rails new) is a strong incentive to try to learn new superpowers:

  • Turbo is the evolution of its predecessor Turbolinks
  • Turbo Streams is an elegant solution that allows the server to deliver page changes to the clients, using ActionCable.
  • Stimulus pairs beautifully with Turbo to provide a complete solution for fast, compelling applications with a minimal amount of effort.

This is the first of a series of articles I intend to share what I learned while studying this exciting framework.

Installing the latest Ruby

My preferred Ruby env manager is rbenv, its ruby-build plugin makes it easier to install multiple versions of Ruby, which is important if you need to work in different projects maintained in different Ruby versions.

% rbenv install --list
2.6.8
2.7.4
3.0.2
jruby-9.3.1.0
mruby-3.0.0
rbx-5.0
truffleruby-21.3.0
truffleruby+graalvm-21.3.0

# Installs the latest ruby version
% rbenv install 3.0.2

Before installing a new ruby version, I’m used to referring to this ruby-build’s build dependencies wiki in order to make sure the OS dependencies are installed correctly.

Installing the Rails gem release candidate

When you try to install the rails gem, it will always fetch the latest stable version:

% gem search -e rails
*** REMOTE GEMS ***
rails (6.1.4.1)

In order to install a release candidate version, it’s needed to append the flag --pre to the install command

% gem install rails --pre
Successfully installed rails-7.0.0.alpha2
Parsing documentation for rails-7.0.0.alpha2
Done installing documentation for rails after 0 seconds
1 gem installed

Tailor the Rails project creation

The command rails new creates a new project with some defaults: it assumes an SQLite database and includes some convenient tools. I personally prefer starting leaner by removing Spring, Bootsnap, CoffeeScript, JBuilder, and the capybara/selenium system tests, I can add them back later if I need them. I also set the css flag to tell Rails to set up Sass as the default CSS processor.

mkdir Demo && cd Demo
rails new . --database=postgresql \
  --skip-bootsnap \
  --skip-spring \
  --skip-coffee \
  --skip-jbuilder \
  --skip-system-test \
  --css=sass

These preferences can be saved into a ~/.railsrc file, so the next time I run the command I can simply type rails new without having to remember to pass all the flags:

# ~/.railsrc
--database=postgresql
--skip-bootsnap
--skip-spring
--skip-coffee
--skip-jbuilder
--skip-system-test
--css=sass

Postgres local setup

I always refer to this guide because creating a role and database with the same name as my host’s username is the easiest way to start working with a local database without having to worry about database credentials. With this setup, Postgres uses a socket file instead of a network hostname and allows the terminal user to access the database without a password.

Any database configuration editions to the application’s config/database.yml file can be done at a later stage. The command below creates the Postgres database, and running db:migrate for the first time generates the file db/schema.rb.

rails db:create db:migrate

slim-rails

I particularly like writing the view templates using Slim over of Erb. The setup is pretty straightforward:

  1. Add slim-rails to the Gemfile and run bundle install
  2. Use the html2slim utility to convert the Rails-generated erb files to slim
    gem install html2slim
    erb2slim app/views -d
    
  3. Setup the extension slim/smart in the config/application.rb:
    require "slim/smart"
    

minitest-rails

I also customize the test framework:

  1. Add minitest-rails to the Gemfile and run bundle install
    group :development, :test do
      # Start debugger with binding.b [https://github.com/ruby/debug]
      # gem "debug", ">= 1.0.0", platforms: %i[ mri mingw x64_mingw ]
      gem 'byebug'
    
      gem 'minitest-rails', github: 'fabiolnm/minitest-rails'
    end
    
  2. Run rails generate minitest:install to add a test_helper.rb file to the test directory.
  3. Configure the rails generators (config/application.rb):
    config.generators do |g|
      g.helper false
      g.system_tests nil
      g.test_framework :minitest, spec: true
    end
    

Add a Home page to verify the generators

The application needs a home page, and it’s something small enough and useful to verify the generators are working as expected:

% rails g controller Home index
      create  app/controllers/home_controller.rb
       route  get 'home/index'
      invoke  slim
      create    app/views/home
      create    app/views/home/index.html.slim
      invoke  minitest
      create    test/controllers/home_controller_test.rb

Excellent! Slim and Minitest generators working as expected. A final adjustment: edit the config/routes.rb to make home#index the root page of the application.

Rails.application.routes.draw do
  root 'home#index'
end

Sass compilation

Remember the application was generated with the --css=sass flag? It’s then necessary to run this command to compile the Sass files into CSS:

% yarn build:css --watch
yarn run v1.22.17
$ sass ./app/assets/stylesheets/application.sass.scss ./app/assets/builds/application.css --no-source-map --load-path=node_modules --watch
Compiled app/assets/stylesheets/application.sass.scss to app/assets/builds/application.css.
Sass is watching for changes. Press Ctrl-C to stop.

Curious about how it works? In the code above, the sass command on the third line is a script that was declared in the package.json file:

{
  "name": "app",
  "private": "true",
  "dependencies": {
    "sass": "^1.43.4"
  },
  "scripts": {
    "build:css": "sass ./app/assets/stylesheets/application.sass ./app/assets/builds/application.css --no-source-map --load-path=node_modules"
  }
}

I prefer the indented Sass syntax over Scss, so I edited the command to:

  "scripts": {
    "build:css": "sass ./app/assets/stylesheets/application.sass ./app/assets/builds/application.css --no-source-map --load-path=node_modules"
  }

Then renamed the application.sass.scss file:

mv app/assets/stylesheets/application.sass.scss app/assets/stylesheets/application.sass

And to test the Sass compilation is working, we can set up a Google Font to this application.sass file:

# app/assets/stylesheets/application.sass
@import url('https://fonts.googleapis.com/css?family=Open+Sans')

:root
  font-family: 'Open Sans', sans-serif

The yarn terminal will compile the sass file:

Compiled app/assets/stylesheets/application.sass to app/assets/builds/application.css.

Running the application

Now it’s the perfect moment to start the rails server and visit the app home page http://localhost:3000:

running.png

Git commit and push

All set, it’s a perfect time to init the Git repository, create the initial commit, and push to GitHub!

git init
git add .
git commit -m "Initial commit"

git remote add origin git@github.com:fabiolnm/hotwire-articles.git
git push --set-upstream origin main
git push

Source code and next articles

This is the repository I’m pushing the code for the articles of the series. The next topics will cover what I learned so far related to Hotwire. Additionally, I’m also learning Docker and Kubernetes, which I will also post about.

About Fábio Miranda

Photo of Fábio Miranda I'm currently living in Vancouver, Beautiful British Columbia, Canada, where my family and I started a new journey in 2023. I'm a hard-worker, currently the CTO at 7GEN, helping to remove the biggest barriers to electrification for medium- and heavy-duty commercial fleets.
Computer Engineer since 2004, graduated from ITA - Instituto Tecnológico de Aeronáutica (Aeronautical Technological Institute). I've been working with software development since then in many different tech stacks (Java, Python, Ruby, Golang, NodeJS) and industries (Aviation, Consulting, Brazilian Payments processing startups, Schools, Fundraising, and Logistics).