# Contributing to Sorbet Rails Thank you for taking the time to contribute to this project! This project adheres to the Contributor Covenant [code of conduct](https://github.com/chanzuckerberg/.github/tree/master/CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to opensource@chanzuckerberg.com. This project is licensed under the [MIT license](LICENSE.md). ## Need Help? If you are trying to integrate Sorbet into your project, consider these venues: * **Stack Overflow**: Try the [sorbet](https://stackoverflow.com/questions/tagged/sorbet) and [sorbet + ruby-on-rails](https://stackoverflow.com/questions/tagged/sorbet+ruby-on-rails) tags * **Slack**: [the Sorbet community](https://sorbet.org/en/community) includes [#discuss](https://sorbet-ruby.slack.com/app_redirect?channel=discuss) and [#rails](https://sorbet-ruby.slack.com/app_redirect?channel=rails) channels If you've come here to report an issue, you're in the right place! ## Reporting Bugs and Adding Functionality We're excited you'd like to contribute to Sorbet Rails! When reporting a bug, please include: * Steps to reproduce * The versions of Ruby, Ruby on Rails, Sorbet, and this gem that you are using * A test case, if you are able **If you believe you have found a security issue, please contact us at security@chanzuckerberg.com** rather than filing an issue here. When proposing new functionality, please include test coverage. We're also available in the Sorbet Slack [#rails](https://sorbet-ruby.slack.com/app_redirect?channel=rails) channel to discuss your idea before you get started, just to make sure everyone is on the same page. ## Local Development 1. Clone `sorbet-rails` locally: ```sh ❯ git clone https://github.com/chanzuckerberg/sorbet-rails.git ``` 2. Point your project's Gemfile to your local clone: ``` # -- Gemfile -- gem 'sorbet-rails', path: "~/sorbet-rails" ``` The most important files are: * [`rbi/activerecord.rbi`](rbi/activerecord.rbi): The ActiveRecord RBI. If you change anything in this file, it will be reflected when you run `srb tc`. * [`lib/sorbet-rails/model_rbi_formatter.rb`](lib/sorbet-rails/model_rbi_formatter.rb): Generates RBI files for models. You can regenerate these using `bundle exec rake rails_rbi:models`. * [`lib/sorbet-rails/routes_rbi_formatter.rb`](lib/sorbet-rails/routes_rbi_formatter.rb): Generates an RBI file for routes. You can regenerate this using `bundle exec rake rails_rbi:routes`. * [`lib/sorbet-rails/helper_rbi_formatter.rb`](lib/sorbet-rails/helper_rbi_formatter.rb): Generates an RBI file for helpers. You can regenerate this using `bundle exec rake rails_rbi:helpers`. ## Tests Tests are written using [RSpec](https://rspec.info/). Each pull request is run against multiple versions of both Ruby and Ruby on Rails. A code coverage report is also generated. ### Running Tests You can run tests using `bundle exec rake`. By default, tests will run against a Rails 5.2.x test application. To run the tests against all supported Rails branches, use: ```sh ❯ ./spec/bin/run_all_specs.sh ``` You can also switch to a version of Rails with `RAILS_VERSION`: ```sh ❯ RAILS_VERSION=5.2 ./spec/bin/run_spec.sh ❯ RAILS_VERSION=6.0 ./spec/bin/run_spec.sh ❯ RAILS_VERSION=6.1 ./spec/bin/run_spec.sh ``` #### Debugging It is possible to run only one file's tests: ```sh ❯ bundle exec rspec spec/model_rbi_formatter_spec.rb ``` Or a specific test in a file: ```sh ❯ bundle exec rspec spec/model_rbi_formatter_spec.rb:28 ``` For debugging, you could use [byebug](https://github.com/deivid-rodriguez/byebug), which is installed in development mode. If you're not familiar with byebug, add `byebug` where you want execution to stop, which will then start a debugger. For more, check out the [byebug guide](https://github.com/deivid-rodriguez/byebug/blob/master/GUIDE.md). ### Writing Tests Tests are in the `_spec.rb` files in the [`spec/`](spec/) directory. Sorbet's `srb tc` test cases are in [`spec/generators/sorbet_test_cases.rb`](spec/generators/sorbet_test_cases.rb). Rails apps are stored in [`spec/support/`](spec/support/). All models, controllers, helpers, migrations, and any other shared code comes from [`spec/generators/rails-template.rb`](spec/generators/rails-template.rb). The only exception to this is `spec/generators/sorbet_test_cases.rb`, which is copied into each app with `cp`. The `rails-template.rb` file uses the [Rails Application Template](https://guides.rubyonrails.org/rails_application_templates.html) functionality included in Rails. You can then regenerate each Rails app from the same file using `bundle exec rake update_spec:v5_0`, `bundle exec rake update_spec:v5_1`, etc. (or just `bundle exec rake update_spec:all`. #### Expected Output If your new tests make changes to the expected output, you can update the expected output by running: ```sh ❯ ./spec/bin/update_test_data.sh ``` Only do this once you're confident that your code is correct, because it will update the expected test data stored in [`spec/test_data/`](spec/test_data/) based on your current code, and all tests will then pass. If you want to update `sorbet_test_cases.rb`, you can run `bundle exec rake update_spec:sorbet_test_cases` to copy the file from `spec/generators/sorbet_test_cases.rb` into each of the Rails apps in `spec/support/`.