Skip to content

Commit b572aba

Browse files
pockeclaude
andcommitted
Say where the gem list comes from when rbs collection init runs
Ask a coding agent to set up RBS and Steep in a project and it usually writes a Steepfile that lists every dependency with `library`, one gem per line. `rbs collection` exists so that nobody has to maintain that list: it reads `Gemfile.lock`, and `rbs` and Steep load the installed RBS files on their own. Agents rarely find it, and the tools we ship are part of why. `rbs collection init` printed one line, `created: rbs_collection.yaml`. It named neither the next command nor the fact that would stop someone from enumerating gems. The generated `rbs_collection.yaml` had the same gap: its comments explained `sources`, `path` and `gems[].ignore` -- the knobs -- but never said the gem list is read from `Gemfile.lock`. The file is read right after it is written, so it is a good place to say so. - `init` now prints what the command does, that gems in `Gemfile.lock` need no listing anywhere, and the next steps: `.gitignore` and `rbs collection install`. `rbs_collection.lock.yaml` is what pins the RBS revisions -- the source is `revision: main` -- so the output says to keep it in version control. - The generated config opens with the same two facts. - Its commented-out `gems:` example showed only `ignore: true`. The other half -- adding an entry for a library that `Gemfile.lock` doesn't carry -- was documented only in `docs/collection.md`. `socket` is the example: it is a non-gem standard library (`NONGEM_STDLIBS`), unlike `pathname`, whose types moved to `core/pathname.rbs` in 8066053, and unlike `csv`, which is in `ALUMNI_STDLIBS` and warns when installed. - `docs/collection.md` gets a quickstart, so readers who see only the first screen get the two commands. Its `cat rbs_collection.yaml` had drifted from the generated file (no `type: git`, no local source comment) and now matches it byte for byte. The `.gitignore` paragraph right below the `init` output is gone, since that output now says it. Ref: #3093 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BXtMkmp27LieHgSjNyEWZ8
1 parent 584b4cf commit b572aba

3 files changed

Lines changed: 73 additions & 12 deletions

File tree

docs/collection.md

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
`rbs collection` sub command manages third party gems' RBS. In short, it is `bundler` for RBS.
44

5+
## Quickstart
6+
7+
In a project that has a `Gemfile.lock`:
8+
9+
```console
10+
$ rbs collection init
11+
$ rbs collection install
12+
```
13+
14+
`rbs collection` reads `Gemfile.lock`, so there is no list of dependencies to maintain. `rbs` and type checkers such as Steep load the installed RBS files automatically.
15+
516
## Requirements
617

718
* `git(1)`
@@ -17,33 +28,44 @@ First, generate the configuration file, `rbs_collection.yaml`, with `rbs collect
1728
$ rbs collection init
1829
created: rbs_collection.yaml
1930

31+
rbs collection installs RBS files for the gems in your Gemfile.lock.
32+
Gems in Gemfile.lock don't need to be listed anywhere.
33+
34+
Next steps:
35+
$ echo "/.gem_rbs_collection/" >> .gitignore
36+
$ rbs collection install # writes rbs_collection.lock.yaml; keep it in version control
37+
2038
$ cat rbs_collection.yaml
39+
# rbs collection installs RBS files for the gems in your Gemfile.lock.
40+
# Run `rbs collection install` to resolve them into rbs_collection.lock.yaml and install them.
41+
2142
# Download sources
2243
sources:
23-
- name: ruby/gem_rbs_collection
44+
- type: git
45+
name: ruby/gem_rbs_collection
2446
remote: https://github.com/ruby/gem_rbs_collection.git
2547
revision: main
2648
repo_dir: gems
2749

50+
# You can specify local directories as sources also.
51+
# - type: local
52+
# path: path/to/your/local/repository
53+
2854
# A directory to install the downloaded RBSs
2955
path: .gem_rbs_collection
3056

3157
# gems:
58+
# # RBS for a library that doesn't appear in Gemfile.lock, such as a non-gem standard library.
59+
# - name: socket
60+
#
3261
# # If you want to avoid installing rbs files for gems, you can specify them here.
3362
# - name: GEM_NAME
3463
# ignore: true
3564
```
3665

37-
I also recommend updating `.gitignore`.
38-
39-
```console
40-
$ echo /.gem_rbs_collection/ >> .gitignore
41-
```
42-
4366
### Install dependencies
4467

4568
Then, install gems' RBS with `rbs collection install`! It copies RBS from [the gem RBS repository](https://github.com/ruby/gem_rbs_collection) to `.gem_rbs_collection/` directory by default.
46-
I recommend to ignore `.gem_rbs_collection/` from version control system, such as Git.
4769

4870
```console
4971
$ rbs collection install
@@ -86,9 +108,9 @@ sources:
86108
path: .gem_rbs_collection
87109

88110
gems:
89-
# If the Gemfile.lock doesn't contain csv gem but you use csv gem,
90-
# you can write the gem name explicitly to install RBS of the gem.
91-
- name: csv
111+
# If the Gemfile.lock doesn't contain socket but you use it,
112+
# you can write the library name explicitly to install RBS of the library.
113+
- name: socket
92114

93115
# If the Gemfile.lock contains nokogiri gem but you don't want to use the RBS,
94116
# you can ignore the gem.

lib/rbs/cli.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1104,6 +1104,9 @@ def run_collection(args, options)
11041104
end
11051105

11061106
config_path.write(<<~'YAML')
1107+
# rbs collection installs RBS files for the gems in your Gemfile.lock.
1108+
# Run `rbs collection install` to resolve them into rbs_collection.lock.yaml and install them.
1109+
11071110
# Download sources
11081111
sources:
11091112
- type: git
@@ -1120,11 +1123,23 @@ def run_collection(args, options)
11201123
path: .gem_rbs_collection
11211124
11221125
# gems:
1126+
# # RBS for a library that doesn't appear in Gemfile.lock, such as a non-gem standard library.
1127+
# - name: socket
1128+
#
11231129
# # If you want to avoid installing rbs files for gems, you can specify them here.
11241130
# - name: GEM_NAME
11251131
# ignore: true
11261132
YAML
1127-
stdout.puts "created: #{config_path}"
1133+
stdout.puts <<~MESSAGE
1134+
created: #{config_path}
1135+
1136+
rbs collection installs RBS files for the gems in your Gemfile.lock.
1137+
Gems in Gemfile.lock don't need to be listed anywhere.
1138+
1139+
Next steps:
1140+
$ echo "/.gem_rbs_collection/" >> .gitignore
1141+
$ rbs collection install # writes rbs_collection.lock.yaml; keep it in version control
1142+
MESSAGE
11281143
when 'clean'
11291144
unless lock_path.exist?
11301145
puts "#{lock_path} should exist to clean"

test/rbs/cli_test.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,30 @@ def foo: () -> void
10821082
end
10831083
end
10841084

1085+
def test_collection_init
1086+
Dir.mktmpdir do |dir|
1087+
Dir.chdir(dir) do
1088+
with_cli do |cli|
1089+
assert_cli_success do
1090+
cli.run(%w(collection init))
1091+
end
1092+
1093+
config = Pathname(dir).join(RBS::Collection::Config::PATH).read
1094+
assert_match(/gems in your Gemfile\.lock/, config)
1095+
assert_match(/rbs collection install/, config)
1096+
1097+
yaml = YAML.load(config)
1098+
assert_equal ".gem_rbs_collection", yaml["path"]
1099+
assert_equal ["ruby/gem_rbs_collection"], yaml["sources"].map {|source| source["name"] }
1100+
1101+
assert_match(/created: .*rbs_collection\.yaml/, stdout.string)
1102+
assert_match(/gems in your Gemfile\.lock/, stdout.string)
1103+
assert_match(/\$ rbs collection install/, stdout.string)
1104+
end
1105+
end
1106+
end
1107+
end
1108+
10851109
def test_collection_install
10861110
omit_on_jruby! "`rbs collection install` runs `bundle install`, which builds native gem extensions that do not compile on JRuby"
10871111

0 commit comments

Comments
 (0)