grape_sorbet is a gem that provides hand written signatures and a Tapioca DSL compiler that makes it more pleasant to use the Grape API framework in Ruby projects that use the Sorbet typechecker.
Install the gem and add to the application's Gemfile by executing:
$ bundle add grape_sorbet
If bundler is not being used to manage dependencies, install the gem by executing:
$ gem install grape_sorbet
After installing the gem, make sure to run bundle exec tapioca gem grape_sorbet
in your project to import the hand written signatures.
Starting with the following example from grape's documentation:
module Twitter
class API < Grape::API
version 'v1', using: :header, vendor: 'twitter'
format :json
prefix :api
helpers do
def current_user
@current_user ||= User.authorize!(env)
end
def authenticate!
error!('401 Unauthorized', 401) unless current_user
end
end
resource :statuses do
desc 'Return a personal timeline.'
get :home_timeline do
authenticate!
current_user.statuses.limit(20)
end
end
end
end
First, you'll need to make the following changes:
- derive from
Grape::API::Instance
rather thanGrape::API
- change the
helpers
call to replace the block parameter with a named module
You'll also need to use T.bind(self, T.all(Grape::Endpoint, <HelpersModuleName>))
in helper methods that use methods provided by Grape (e.g. env
in current_user
or error!
in authenticate!
) or other methods from the same helper module (e.g. current_user
in authenticate!
).
With the changes:
module Twitter
class API < Grape::API::Instance
version 'v1', using: :header, vendor: 'twitter'
format :json
prefix :api
module Helpers
def current_user
T.bind(self, T.all(Grape::Endpoint, Helpers))
@current_user ||= User.authorize!(env)
end
def authenticate!
T.bind(self, T.all(Grape::Endpoint, Helpers))
error!('401 Unauthorized', 401) unless current_user
end
end
helpers Helpers
resource :statuses do
desc 'Return a personal timeline.'
get :home_timeline do
authenticate!
current_user.statuses.limit(20)
end
end
end
end
At this point Sorbet is still reporting errors in the get :home_timeline
block, because it doesn't know that these blocks are executed in a context where the Helpers
module methods will be available. The Tapioca compiler provided by this gem will fix that. Run bundle exec tapioca dsl
. This should generate a sorbet/rbi/dsl/twitter/api.rbi
file (assuming the source file is in lib/twitter/api.rb
).
After this, Sorbet should no longer report any errors.
Grape overrides Grape::API.new
and uses the inherited
hook so that subclasses of Grape::API
are really subclasses of Grape::API::Instance
.
This might be fixable in a future update of grape_sorbet, but is very low priority.
Possibly fixable in a future update.
Possibly fixable in a future update.
Having to use T.bind(self, T.any(Grape::Endpoint, <HelpersModuleName>))
in before
and after
callback blocks
The compiler already generates proper signatures for callback methods so T.bind
should not be needed (and is in fact unneeded for the other callback methods, before_validation
, after_validation
and finally
). The reason it doesn't work for before
and after
is because of a bug in Sorbet itself.
After checking out the repo, run bin/setup
to install dependencies. Then, run rake test
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and the created tag, and push the .gem
file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/thatch-health/grape_sorbet. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the TestGem project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.