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 .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.
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
.
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.
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.
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 bundle install
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 spec/rails_helper.rb
file.
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.
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.
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.