A Template for Starting New Projects on Ruby on Rails

6,234 reads

@ wscourge Wiktor Plaga Ruby on Rails developer

In this story, I want to show you how to bring your Ruby on Rails development to the next level.

reactions

Like often in programming, all it takes is automating repetitive stuff.

reactions

One task that begs for automation in the Ruby on Rails development is starting new projects.

reactions

If from day one you care about:

reactions

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.

reactions

All this stuff we need...

Starting new Ruby on Rails project is like:

reactions

No, seriously - so much stuff to do:

reactions

Damn, that's a handful.

reactions

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.

reactions

Not to mention sending emails in development to some random folks, and doing it synchronously, cause "ah,

ActiveWork

reactions

, yeah I heard".

Or, let's skip logging errors and leave the default logger only. Then enroll the MVP blindfolded.

reactions

And.. have you noticed? Not a word yet about:

reactions

Deployment, not to mention a Continuous Delivery and staging , preprod and whatnot environment. Front-end setup, that nowadays, with rich JavaScript doubles some of those points: like linting, separate tests.

Don't get me wrong, I love Ruby on Rails, it's still my favorite - so much stuff out of the box.

reactions

Just all this configuration is what, like two, three workdays?

reactions

Disclaimer: it's minutes with Hix on Rails Application Template.

reactions

Default Ruby on Rails options

Before we get to the template, one cool thing worth mentioning with Rails are the default

new

reactions

options.

When using

rails new

reactions

$ rails new -- help Usage: rails new APP_PATH [options] Options: [--skip-namespace], [--no-skip-namespace] # Skip namespace (affects only isolated applications) -r, [--ruby=PATH] # Path to the Ruby binary of your choice # Default: /usr/share/rvm/rubies/ruby-2.6.1/bin/ruby -m, [--template=TEMPLATE] # Path to some application template (can be a filesystem path or URL) -d, [--database=DATABASE] # Preconfigure for selected database (options: mysql/postgresql/sqlite3/oracle/frontbase/ibm_db/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc) # Default: sqlite3 [--skip-gemfile], [--no-skip-gemfile] # Don't create a Gemfile -G, [--skip-git], [--no-skip-git] # Skip .gitignore file [--skip-keeps], [--no-skip-keeps] # Skip source control .keep files -M, [--skip-action-mailer], [--no-skip-action-mailer] # Skip Action Mailer files [--skip-action-mailbox], [--no-skip-action-mailbox] # Skip Action Mailbox gem [--skip-action-text], [--no-skip-action-text] # Skip Action Text gem -O, [--skip-active-record], [--no-skip-active-record] # Skip Active Record files [--skip-active-storage], [--no-skip-active-storage] # Skip Active Storage files -P, [--skip-puma], [--no-skip-puma] # Skip Puma related files -C, [--skip-action-cable], [--no-skip-action-cable] # Skip Action Cable files -S, [--skip-sprockets], [--no-skip-sprockets] # Skip Sprockets files [--skip-spring], [--no-skip-spring] # Don't install Spring application preloader [--skip-listen], [--no-skip-listen] # Don't generate configuration that depends on the listen gem -J, [--skip-javascript], [--no-skip-javascript] # Skip JavaScript files [--skip-turbolinks], [--no-skip-turbolinks] # Skip turbolinks gem -T, [--skip-test], [--no-skip-test] # Skip test files [--skip-system-test], [--no-skip-system-test] # Skip system test files [--skip-bootsnap], [--no-skip-bootsnap] # Skip bootsnap gem [--dev], [--no-dev] # Setup the application with Gemfile pointing to your Rails checkout [--edge], [--no-edge] # Setup the application with Gemfile pointing to Rails repository [--rc=RC] # Path to file containing extra configuration options for rails command [--no-rc], [--no-no-rc] # Skip loading of extra configuration options from .railsrc file [--api], [--no-api] # Preconfigure smaller stack for API only apps -B, [--skip-bundle], [--no-skip-bundle] # Don't run bundle install --webpacker, [--webpack=WEBPACK] # Preconfigure Webpack with a particular framework (options: react, vue, angular, elm, stimulus) [--skip-webpack-install], [--no-skip-webpack-install] # Don't run Webpack install Runtime options: -f, [--force] # Overwrite files that already exist -p, [--pretend], [--no-pretend] # Run but do not make any changes -q, [--quiet], [--no-quiet] # Suppress status output -s, [--skip], [--no-skip] # Skip files that already exist Rails options: -h, [--help], [--no-help] # Show this help message and quit -v, [--version], [--no-version] # Show Rails version number and quit Description: The 'rails new' command creates a new Rails application with a default directory structure and configuration at the path you specify. You can specify extra command-line arguments to be used every time 'rails new' runs in the .railsrc configuration file in your home directory. Note that the arguments specified in the .railsrc file don't affect the defaults values shown above in this help message. Example: rails new ~/Code/Ruby/weblog This generates a skeletal Rails installation in ~/Code/Ruby/weblog.

, 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.

reactions

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.

reactions

If that's the case, you can define the magic ~/.railsrc file in your home directory, with initialization flags that you always use.

reactions

touch ~/.railsrc vi ~/.railsrc

For example, my looks like this:

reactions

--database=postgresql --skip-spring --skip-test --webpack=react --template=https://hixonrails.com/template.rb

Here, I tell every

rails new

reactions

go Postgres! nope Spring nope MiniTest, I want RSpec go React!

command on my system:

And the last thing: use the Rails Application Template.

reactions

Say what?

reactions

Ruby on Rails - Application Template

Ruby on Rails Application Templates are simple files with a Domain Specific Language.

reactions

You can add stuff to the brand new Ruby on Rails project - initializers, gems, rake tasks - you name it.

reactions

rails new project --template /path/to/template.rb rails new project --template https://example.com/template.rb

Simple, yet so powerful.

reactions

The template code runs after the initial Rails configuration, and before the bundle installs.

reactions

That means that you can:

reactions

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.

reactions

For example: create a remote git repository via Github or Gitlab API.

reactions

Afterwards add the git remote to the project.

reactions

So cool.

reactions

Template DSL

Let's now take a quick look what we can do using Rails App Template specific language:

reactions

Install and group gems by environments with gem and gem_group Declare gem sources with add_source method Write to declared environment files Write lib , initializer , vendor , rakefile and any file with HEREDOC Gather user input with ask , yes? and no? methods and run other stuff conditionally Launch rails generator for scaffold, migration, model, controller, whatever Execute git commands Explicitly run selected code after_bundle installs. Execute shell commands with the run method.

That's a lot of useful stuff right here, so let's see it in action.

reactions

Rails Application Template with static code analysis

Let's give some of the methods a spin by setting up a really simple Rails Application Template, that:

reactions

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.

reactions

First, let's create our template.rb file and open it with a text editor.

reactions

vi ~/ws/articles/hackernoon/template.rb

Next, let's install all the RuboCop gems in the

development

test

reactions

# frozen_string_literal: true gem_group :development , :test do gem 'rubocop' gem 'rubocop-performance' gem 'rubocop-rails' end

andenvironments:

Now that we have those in place, let's tell Rails to add the .rubocop.yml file, so we can loose up those restrictions a little.

reactions

Add the following code.

reactions

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.

reactions

The last thing is to clean up the default Rails code with RuboCop after the project initializes, and when all RuboCop gems are available.

reactions

Hint: after bundle installs.

reactions

Add the following code:

reactions

after_bundle do run 'bundle exec rubocop --auto-correct' end

At the point of writing this article, with Rails 6.0.2.1, it fixed 75 of 78 offenses automatically, so I needed to do some work manually.

reactions

$ 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.

reactions

Less hardcore option is using the

--safe-auto-correct

FrozenStringLiteral

reactions

, though it recently stopped to fix the missingand 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.

reactions

after_bundle do run 'bundle exec rubocop --auto-gen-config' end

It does two things:

reactions

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.

reactions

Now all that's left to be done is launching the Rails installer pointing to our new template file:

reactions

rails new project_name --template=/path/to/local/template.rb

Sit back and relax - it all happens automatically. Cool, huh?

reactions

When to use Rails Application Template

Everytime, really, cause why the hell not.

reactions

But for some it is a goldmine:

reactions

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.

reactions

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.

reactions

There's even a company that I know for a fact that uses their own application template, cause they open-sourced it.

reactions

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.

reactions

Last, Corporations, or any micro services freaks, even smaller companies.

reactions

I'd say that if you:

reactions

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.

reactions

If you like to compartmentalize stuff into small Ruby on Rails pieces, Application Templates are the way to go.

reactions

What's the problem with Rails Application Template?

Maintenance. You won't use it that often.

reactions

Rails itself, same as a lot of gems that you happily use, evolve.

reactions

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.

reactions

Worry not though, cause those are exact reasons why Hix on Rails decided to take care of all the up-to-date stuff, so you can focus on what really matters for you.

reactions

Just get to the point and implement business logic after completing a short wizard in the CLI. Painlessly, simple as that.

reactions

Conclusion

So, how do you like the concept of automating Ruby on Rails projects initialization?

reactions

Do you have in mind anything that would be so cool to go into the Rails Application Template?

reactions

Maybe you already use templates yourself, and I've missed something?

reactions

I'd love your feedback - please, tell me in comments!

reactions

Tags