In this story, I want to show you how to bring your Ruby on Rails development to the next level.
Like often in programming, all it takes is automating repetitive stuff.
One task that begs for automation in the Ruby on Rails development is starting new projects.
If from day one you care about:
- Code quality,
- Easy maintenance,
- Good performance,
- Code that’s pleasant to work with,
then you’ve come to the right place – let’s see why.
All this stuff we need…
Starting new Ruby on Rails project is like:
No, seriously – so much stuff to do:
- Install the latest stable Ruby version – check.
- Install the latest stable Ruby on Rails version – check.
- Install the latest stable database version: MySQL, PostgreSQL, you name it – check.
- Prepare strict separation of config from code: Rails credentials, Dotenv, Figaro – check.
- Create a new git remote repository: Github, Gitlab, Bitbucket – check.
- Install the latest stable Redis version – check.
- Configure ActionCable to use Redis in development to keep the gap between production and development small – check
- Async code execution, like Sidekiq – check.
- Create a new project on the monitoring cloud: Rollbar, Sentry, Honeybadger, Bugsnag, Airbrake, Skylight – check.
- Prepare a cloud storage bucket: Microsoft Azure Blob Storage, Google Cloud Storage, Amazon S3 – check.
- Prepare SMTP or email sending API settings: Amazon SES, Gmail, Mailgun, Mandrill, SendGrid – check.
- Send emails in development: MailCatcher, LetterOpener – check.
- Prepare RSpec configuration for testing, and try not forgetting any of the following: DatabaseCleaner, FactoryBot, TimeCop, Rspec Sidekiq Testing, VCR – check.
- Oh yeah, code coverage with SimpleCov and Coveralls – yeah, I forgot when talking about RSpec – check.
- Keep the bar up: RuboCop, RuboCop Performance, RuboCop RSpec, RuboCop Rails, Fasterer, Brakeman, Dawnscanner, Bundle Audit, Rails Best Practices – check.
- Set up this whole standardized-code-3rd-reich in the Continuous Integration – Github Actions, GitlabCI, Bamboo, CircleCI, Travis – check.
Damn, that’s a handful.
Now, try for example to not keep the bar up from the first commit, and someone will take a crap in the middle of your code base – happily.
, yeah I heard”.
Or, let’s skip logging errors and leave the default logger only. Then enroll the MVP blindfolded.
And.. have you noticed? Not a word yet about:
- Deployment, not to mention a Continuous Delivery and
Don’t get me wrong, I love Ruby on Rails, it’s still my favorite – so much stuff out of the box.
Just all this configuration is what, like two, three workdays?
Default Ruby on Rails options
, we are able to tell Rails to do / do not use certain parts of the framework.
And there’s a handful to remember, as you can see.
If you already built some Ruby on Rails apps, you probably have a list of options you don’t like, or you’re in the PostgreSQL or MySQL camp.
If that’s the case, you can define the magic ~/.railsrc file in your home directory, with initialization flags that you always use.
touch ~/.railsrc vi ~/.railsrc
For example, my looks like this:
--database=postgresql --skip-spring --skip-test --webpack=react --template=https://hixonrails.com/template.rb
command on my system:
- go Postgres!
- nope Spring
- nope MiniTest, I want RSpec
- go React!
Ruby on Rails – Application Template
You can add stuff to the brand new Ruby on Rails project – initializers, gems, rake tasks – you name it.
rails new project --template /path/to/template.rb rails new project --template https://example.com/template.rb
Simple, yet so powerful.
The template code runs after the initial Rails configuration, and before the bundle installs.
That means that you can:
- Override every file generated
- Add any gems you want
- Create new files
- Create database tables
On top of that, you can run any shell command.
For example: create a remote git repository via Github or Gitlab API.
Afterwards add the git remote to the project.
Let’s now take a quick look what we can do using Rails App Template specific language:
- Install and group gems by environments with
- Declare gem sources with
- Write to declared
- Gather user input with
methods and run other stuff conditionally
- Launch rails
for scaffold, migration, model, controller, whatever
- Explicitly run selected code
- Execute shell commands with the
That’s a lot of useful stuff right here, so let’s see it in action.
Rails Application Template with static code analysis
Let’s give some of the application template methods a spin by setting up a really simple Rails Application Template, that:
- Installs and uses RuboCop by default
- Installs and requires RuboCop Performance extension
- Installs and requires RuboCop Rails extension
So here’s how to do that.
First, let’s create our template.rb file and open it with a text editor.
# frozen_string_literal: true gem_group :development, :test do gem 'rubocop' gem 'rubocop-performance' gem 'rubocop-rails' end
Now that we have those in place, let’s tell Rails to add the .rubocop.yml file, so we can loose up these Ruby nazi a little.
Add the following code.
file '.rubocop.yml', <<-CODE require: - rubocop-rails - rubocop-performance AllCops: Exclude: - node_modules/**/* - db/** - db/migrate/** - bin/** - vendor/**/* Layout/LineLength: Max: 120 Metrics/BlockLength: Exclude: - config/**/* Style/Documentation: Enabled: false CODE
That’s going to write our RuboCop configuration file in the root of the new Ruby on Rails application initialized with the template.
The last thing is to clean up the default Rails code with RuboCop after the project initializes, and when all RuboCop gems are available.
Hint: after bundle installs.
Add the following code:
after_bundle do run 'bundle exec rubocop --auto-correct' end
At the point of writing this article, with Rails 22.214.171.124, it fixed 75 of 78 offenses automatically, so I needed to do some work manually.
$ bundle exec rubocop Inspecting 31 files .............C...............CC Offenses: config/environments/development.rb:19:6: C: Rails/FilePath: Please use Rails.root.join('path/to') instead. if Rails.root.join('tmp', 'caching-dev.txt').exist? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/channels/application_cable/connection_test.rb:5:7: C: Style/ClassAndModuleChildren: Use nested module/class definitions instead of compact style. class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ test/test_helper.rb:7:7: C: Style/ClassAndModuleChildren: Use nested module/class definitions instead of compact style. class ActiveSupport::TestCase ^^^^^^^^^^^^^^^^^^^^^^^ 31 files inspected, 3 offenses detected
Not so much though.
, though it recently stopped to fix the missing
and will require you to manually add it to each file – and it’s worth it.
For those chickens who don’t like code that writes code, there’s a lightweight alternative that’ll point to all the violated lines in the special .rubocop_todo.yml file.
after_bundle do run 'bundle exec rubocop --auto-gen-config' end
It does two things:
- Launches a dry run of RuboCop, that writes .rubocop_todo.yml with violated files excluded from the next RuboCop runs
- Edits .rubocop.yml file, telling it to mind the exclusions
This way you can make sure that RuboCop’s auto-correction does not beak anything, by fixing it all one by one, by hand. No YOLO though.
Now all that’s left to be done is launching the Rails installer pointing to our new template file:
rails new project_name --template=/path/to/local/template.rb
Sit back and relax – it all happens automatically. Cool, huh?
When to use Rails Application Template
Everytime, really, cause why the hell not.
But for some it is a goldmine:
Software Houses: let’s say one project a week, doing all this stuff – I can only imagine that there’s this one go-to guy, probably mid to senior level, that sets the stuff up, for one to three working days.
I remember my co-worker telling me a story about someone, who worked at a Software House and once per two weeks he was literally installing the same gems in a next new project all over again.
Next, Freelancers: if you happen to take on some work and code in Ruby on Rails, it’s a great way to speed up the process.
Last, Corporations, or any micro services freaks, even smaller companies.
I’d say that if you:
- Maintain around five Ruby on Rails projects already,
- Keep certain coding standards in your development team,
it’s time to extract the commonly used stuff to the template before starting the next project.
If you like to compartmentalize stuff into small Ruby on Rails pieces, Application Templates are the way to go.
What’s the problem with Rails Application Template?
Maintenance. You won’t use it that often.
Rails itself, same as a lot of gems that you happily use, evolve.
You can lock the gems versions, but it’s not the best idea – it’s better to use the latest stable versions available, for a security reasons if not for anything else.
Just get to the point and implement business logic after completing a short wizard in the CLI. Painlessly, simple as that.
So, how do you like the concept of automating Ruby on Rails projects initialization?
Do you have in mind anything that would be so cool to go into the Rails Application Template?
Maybe you already use templates yourself, and I’ve missed something?
I’d love your feedback – please, tell me in comments!