Duetcode

Create a new rails application and setup boilerplate

27 June 2020

Create a new API-only rails application

We will use ruby version 2.6.5 and rails 6.0.2 for the new rails application, but I will skip how to install those since I already stated in the introduction page that the target audience should be familiar with rails and ruby technology stack. (UPDATE: You can use ruby -v and rails -v commands to check you installed both of them.)

Let’s start by creating a new API-only rails application, which we named bookmarker.

~/code rails new --api --database postgresql --skip-spring --skip-action-cable --skip-action-mailbox --skip-test bookmarker
  • --api: We specified this flag to have API-only rails application. It will not load dependencies regarding the view layer.
  • --database postgresql: We used PostgreSQL as a relational database. The flag preconfigures our rails application to use PostgreSQL.
  • --skip-spring: I’m not a big fan of working with spring since it’s getting difficult to understand the problems caused by spring while debugging, and also rails uses bootsnap by default, which is already performant enough without spring. You can check the performance of discourse application that uses only bootsnap from @samsaffron’s tweet.
  • --skip-action-cable: We also didn’t use action cable since our app doesn’t need any realtime data synchronization between the server and client-side.
  • --skip-action-mailbox: We skipped the action mailbox because we don’t have any use case of action mailbox for our application.
  • --skip-test: We also used skip test flag since we’re going to have rspec instead of rails testing defaults.

It’s intuitive to think about adding .gitignore and .ruby-version files at this point, but ruby on rails already generates them for us. We can modify the .gitignore file later if we think we need to ignore more files for version control, but it’s enough to keep it as is for now.

Setup rubocop gem

We will also use rubocop as linter/formatter for our project. It will guide us to keep common conventions for the codebase. Let’s install rubocop gem to the development and test groups of the Gemfile.

Gemfile
group :development, :test do
  # ...

  gem 'rubocop', '~> 0.85.1', require: false
end

After that, let’s run bundle exec rubocop --auto-correct command to auto-correct the initial boilerplate generated by rails. Then execute bundle exec rubocop --auto-gen-config to create both .rubocop.yml and .rubocop_todo.yml files.

As the name suggests, rubocop_todo.yml file shows the configuration regarding the current offenses in the codebase. The purpose of having a todo file to remove offenses and delete those configurations step by step eventually. But personally, I would like to keep them as is, since they got some offenses not because of my code but because of the ruby on rails boilerplate, which is not going to reflect our business domain. The only part I would like to change is method length configuration, which I want to keep as 7 lines long maximum, and now I can move this part back to .rubocop.yml file.

.rubocop.yml
inherit_from: .rubocop_todo.yml

Metrics/MethodLength:
  Max: 7
  Exclude:
    - 'bin/bundle'

I also excluded bin/bundle from the configuration because it had 12 lines long methods that I don’t see any clear advantage of refactoring. Now, if you run bundle exec rubocop, you shouldn’t see any offenses come from rubocop gem.

Instead of running bundle exec rubocop every time, you can add an alias to rubocop command as bundle exec rubocop in your computer’s .bash_profile or .zshrc file if you’re using zsh. Alternatively, you can also alias bundle exec to be command and run be rubocop or be rspec etc. with be alias. To get more information about how to add an alias, you can check thoughtbot’s blog post.

Create databases for development and test environments

As a part of the boilerplate setup, we need to run rails db:create command to create development and test databases. Before creating databases, make sure that you already installed PostgreSQL, and it’s running on your computer.

Setup essential gems for testing

We also need to set up essential gems for testing. We will use rspec as a testing framework, so let’s start with adding rspec-rails gem to development and test groups of Gemfile and run bundle install

Gemfile
group :development, :test do
  # ...

  gem 'rspec-rails', '~> 4.0'
  gem 'rubocop', '~> 0.85.1', require: false
end

Then, we need to run rails generate rspec:install command to create configuration files for rspec setup.

~/code/bookmarker (master) rails generate rspec:install

  create  .rspec
  create  spec
  create  spec/spec_helper.rb
  create  spec/rails_helper.rb

And, we also need to install factory_bot_rails gem as a fixtures replacement. We will use factory bot mostly for simulating activerecord instances.

Gemfile
group :development, :test do
  # ...

  gem 'factory_bot_rails', '~> 5.2'
  gem 'rspec-rails', '~> 4.0'
  gem 'rubocop', '~> 0.85.1', require: false
end

Besides rspec and factory bot gems, we need shoulda-matchers to be able to test common rails functionality.

Gemfile
group :test do
  gem 'shoulda-matchers', '~> 3.1'
end

And after that, we need to configure spec/rails_helper.rb to use shoulda-matchers. So place following configuration block at the bottom of spec/rails_helper.rb file.

spec/rails_helper.rb
Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails
  end
end

And lastly, the general intention at this stage will be adding database cleaner gem to the application, but rails already provides this functionality with use_transactional_tests. (Previously it was called as use_transactional_fixtures, and it changed in rails 5 because the name was misleading.) To make it more clear, we’re using this feature inside of rails_helper.rb file with config.use_transactional_fixtures = true line which is actually calling use_transactional_tests internally by rspec-rails gem.

Using transactional tests basically allows us to run each test inside of the database transaction and rollbacks all the changes just before the test is completed. So our test database is going to be in the same state at the beginning of the test and at the end of the test. It’s funny that personally, I saw database_cleaner gem in most of my previous work-related projects, but actually, that was implemented in rails a long time ago. You can see the @dhh’s commit from 2005.

Version control

I don’t want to involve in how to commit those code changes into the git, but I would recommend keeping the commits as small as possible so that the next person can understand the context easily. And also don’t forget to run rubocop before committing the changes. You can also add rubocop and rspec to Rakefile and then run rake command to see both of their results together. (See how to use Rakefile with rspec and rubocop.) Ideally, you should have both of them in the continuous integration process. If you encounter any offense that can be auto corrected then you can use bundle exec rubocop --auto-correct command to solve offenses, but make sure that you’re not using --auto-correct flag in CI process because you would like to see offenses instead of solving them there.

Summary

In this chapter, we learned how to setup rails API-only application boilerplate with essential testing gems. You can find the source code of bookmarker application on github. In the next chapter, we’re going to create the User model and the user creation endpoint with using devise gem. You can also read the previous introduction chapter.

Thanks for reading! I would love to hear your feedback about the chapter and the course in general. You can contact me by email or from twitter.