Using Sorbet and Tapioca with Rails

The Sorbet team recently started recommending that you use Tapioca to generate RBI files. I introduced Sorbet and Tapioca to some of our Rails apps at work a few months ago. My team and I found some parts confusing, but overall it’s been working well for us.

Here are some things we learned.

Installing

Add these to your Gemfile and install them. Feel free to organize it how you wish—I like keeping related gems together.

gem "sorbet", group: :development
gem "sorbet-runtime"
gem "spoom", require: false, group: :development
gem "tapioca", require: false, group: :development

Installing Spoom is optional. I’ll talk about it later.

Getting started

You’ll basically need to run the commands detailed in the Tapioca readme in order. I won’t go into too much detail here since that resource is more likely to be kept updated, but here’s what you need to run at a minimum:

  • tapioca init
  • tapioca gem
  • tapioca dsl

I also run tapioca require and tapioca todo too. Ideally, by adding custom require calls to sorbet/tapioca/require.rb, you should be able to make sorbet/rbi/todo.rbi empty. The readme should have more information.

I haven’t used tapioca annotations enough to give you any suggestions there. However, it adds several errors, some of which are false negatives. I’ll continue considering it, but I’m unlikely to use it in production for another few releases (as of Aug 2022).

After running those commands, running the type checker will probably result in a bunch of errors. Again, the readme shows you how to resolve them.

Verifying your types

You can run spoom tc or srb tc to type-check your application. I recommend using Spoom because it doesn’t suggest fixes. I noticed that many of its suggested fixes were incorrect, but I’m sure this will improve over time.

Regardless of what you decide to use, the results are identical and largely interchangeable.

Maintaining your app

  • After installing or updating gems, you need to run this:
    • tapioca gem
    • tapioca dsl (You probably only need to run this if you’ve updated Tapioca)
  • After running database migrations
    • tapioca dsl
  • After updating the routes file
    • tapioca dsl

When we first started using Sorbet, we found that we often forgot to run those above commands. By adding these following checks into your CI pipeline, you can make sure that the sorbet directory is kept updated.

bundle exec tapioca gems --verify
bundle exec tapioca dsl --verify

Making sure new code is typed

Adoption. How do we get people to use Sorbet?

I don’t have a good answer for this. I originally used Spoom to check for what percentage of code was typed, and I made a test that failed when not enough code was typed. This didn’t work very well since we tended not to write types for our specs.

One thing that might have helped was that I commented on PRs with suggested type signatures. But I think that Sorbet itself encourages usage. Eventually, my team did start writing types without my suggesting it!

Final tips

  • You don’t need the sorbet-rails gem
  • Never run any command that starts with srb rbi
  • If you’ve been using sorbet-rails and/or srb rbi, I’d probably recommend deleting your sorbet directory and starting from scratch
  • Some methods can’t be typed! Some frameworks check the method signature of a method before calling it. Sorbet changes the method signature of typed methods, so some files can’t have strict type checking
  • Spoom isn’t a typo! It’s some kind of dessert

Sorbet and Tapioca has been working very well for us in our Rails apps! I definitely recommend looking into it.

Posted on 2022-08-01 07:42 PM -0400
Contact
hello(at)zachahn(dot)com
© Copyright 2008–2022 Zach Ahn