Add types to generated RBI files for FrozenRecord
Motivation
This change is motivated by some work by team has been doing using FrozenRecord/FrozenApplicationRecord in Core. We noticed that Sorbet wasn't really giving us useful typing information for fields where we expected and looking at the generated RBI file, I saw that each field is typed as T.untyped.
I wanted to see if there was a relatively straightforward change that would improve the typing without a dev having to do a whole lot. Upon further digging and a Slack discussion it seems like another issue is that all the accessor methods are marked as T.untyped, too, which means Record.first (as an example) comes back as T.untyped which means doing things like:
first_name = Record.first.first_name
all_nick_ages = Record.where(first_name: "Nick").order(age: :desc).pluck(:age)
returns in everything being T.untyped, which isn't helpful. Devs are forced to do things like:
first_name = T.let(Record.first.first_name, String)
all_nick_ages = T.let(Record.where(first_name: "Nick").order(age: :desc).pluck(:age), T::Array[Integer])
this becomes a little more frustrating when you're not dealing with an individual field, but with the Record entirely:
# first_record is typed as Record, but the fields are T.untyped
# and defining each field sucks
first_record = T.let(Record.first, Record)
all_nick_records = T.let(Record.where(first_name: "Nick").order(age: :desc), T::Array[Record])
# all_nick_records[0].first_name is T.untyped
So my motivation is to at least make doing T.let(..., Record) the only thing a dev needs to do to get reasonable typing.
If this change is accepted, the next step would be to better type the methods available as part of FrozenRecord (e.g. find, where, order) since we should know (I think?) that calling Record.find(...) returns T.nilable(Record).
Implementation
The implementation depends on the ActiveModel::Attributes functionality that's used in Rails to explicitly define attribute :my_field, :string for each of the fields that we care to type.
Tests
I added a new unit test with a variety of field types to exercise this functionality and have left comments on this PR where I think we could do better, or areas we should consider for further implementation/testing.