• Time: 10-15 min
  • Level: Intermediate
  • Code: Application
  • Revision: Oct 30, 24

TL;DR - I have a custom/ folder in my project where I keep files that I change instead of modifying generated files. The only change in generated files is customization loading. As a result when I need to upgrade a project I overwrite default files with bin/rails new and add a few require "custom/file.rb" statements.

Since Rails 8 will be released soon I decided to test my custom application layout and upgrade prototype I use for my pet projects from Rails 7 to Rails 8. I will go over the whole process step by step and maybe customization that made it easy will become one you’d like to try yourself.

The only feature application has is an authentication with devise so I (almost) did not have any issues with app functionality or changes introduced in Rails 8.

Section I - Updating project files to Rails 8

  1. Change rails version in the Gemfile
    - gem "rails", "~> 7.1.3", ">= 7.1.3.4"
    + gem "rails", "~> 8.0.0.rc1"
    
  2. Delete Gemfile.lock
  3. Uninstall all gems (gem uninstall --all --force -x)
  4. Install bundler (gem install bundler)
  5. Install rails (bundle)
  6. Update project files (rails new prototype -f -d postgresql -c tailwind)
    • The command is one I used to generate project in the past. Depending on the situation, you could also use bin/rails app:update --force
  7. Commit everything

Section II - Bringing back customization

At this point I couldn’t run the project because some files have been overwriten with default versions provided by the generator. So next I reviewed changes and put back customiztions. Fortunately my project has just a few files that have changes and changes are minimal.

While reviewing I saw changes like

- # Ignore all environment files (except templates).
+ # Ignore all environment files.
  /.env*
- !/.env*.erb

and

  # Throw-away build stage to reduce size of final image
- FROM base as build
+ FROM base AS build

that made my inner perfectionista quite happy :) (also an indicator that people do care)

Overall I had to change eleven files:

links don’t open changes in each file unfortunately, so please use the file tree on the left

These changes introduced new gems so I had to run bundle once more to install them.

That’s all - I was able to start the server and saw the sign in UI.

Section III - Few final touches

One last part was to check if Rubocop checks and RSpec suite pass. I run bin/rubocop -A . to fix the first one and had to change the test I have to make it pass.

Section IV - Custom project layout

Problem: Changes to generated project files interfere wit use of bin/rails new yourprojectname as an upgrade mechanism.

Idea: Changes to generated files have to be minimal in order to put them back easily.

Implementation: Have separate files with changes and load them in generated files.

In order to achieve the desired outcome (simple upgrade process) four mechanisms are used:

  • require "../file.rb" - pain ruby
  • eval_gemfile "../Gemfile" - provided by the bundler gem
  • paths["file.rb"] = - provided by Rails
  • initializer "name", after: :callback do - provided by Rails
  • inherit_from: filename - provided by rubocop gem

Whenever there is a need to change the generated file I introduce new file where I add the change and load a file with change from the original file. Naming convention I use - customization file has the same name as the generated with custom/ prefix. So custom configuration for .rubocop.yml is in custom/.rubocop.yml etc.

Part of the customization resides in custom/config/application.rb which is required in config/application.rb so these changes are preserved while project is upgraded and later introduced again.

Summary

Separation of generated by default project files and customizations made upgrade process much simpler for me. Since customization is done with built-in tools it’s quite simple to implement and having the naming convention makes it easy to understand and follow.

Extra

While I was working on this post 8.0.0.rc2 was released and it took me just a few minutes to upgrade the project.

Revisions

  • Oct 30, 24 - Initial post