27 June 2020
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.
--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
.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.
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
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
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
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
.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.
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.
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
Then, we need to run
rails generate rspec:install command to create configuration files for rspec setup.
And, we also need to install
factory_bot_rails gem as a fixtures replacement. We will use factory bot mostly for simulating activerecord instances.
Besides rspec and factory bot gems, we need
shoulda-matchers to be able to test common rails functionality.
And after that, we need to configure
spec/rails_helper.rb to use shoulda-matchers. So place following configuration block at the bottom of
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
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.
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
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.
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.