AI prompts
base on Type Signature for Ruby # RBS
RBS is a language to describe the structure of Ruby programs.
You can write down the definition of a class or module: methods defined in the class, instance variables and their types, and inheritance/mix-in relations.
It also allows declaring constants and global variables.
The following is a small example of RBS for a chat app.
<!-- run-start:a.rbs:bundle exec rbs -I a.rbs validate -->
```rbs
module ChatApp
VERSION: String
class User
attr_reader login: String
attr_reader email: String
def initialize: (login: String, email: String) -> void
end
class Bot
attr_reader name: String
attr_reader email: String
attr_reader owner: User
def initialize: (name: String, owner: User) -> void
end
class Message
attr_reader id: String
attr_reader string: String
attr_reader from: User | Bot # `|` means union types: `#from` can be `User` or `Bot`
attr_reader reply_to: Message? # `?` means optional type: `#reply_to` can be `nil`
def initialize: (from: User | Bot, string: String) -> void
def reply: (from: User | Bot, string: String) -> Message
end
class Channel
attr_reader name: String
attr_reader messages: Array[Message]
attr_reader users: Array[User]
attr_reader bots: Array[Bot]
def initialize: (name: String) -> void
def each_member: () { (User | Bot) -> void } -> void # `{` and `}` means block.
| () -> Enumerator[User | Bot, void] # Method can be overloaded.
end
end
```
<!-- run-end -->
## The Target Version
* The standard library signatures targets the latest release of Ruby. (`3.2` as of 2023.)
* The library code targets non-EOL versions of Ruby. (`>= 3.0` as of 2023.)
## Installation
Install the `rbs` gem. `$ gem install rbs` from the command line, or add a line in your `Gemfile`.
```rb
gem "rbs"
```
## CLI
The gem ships with the `rbs` command line tool to demonstrate what it can do and help develop RBS.
```console
$ rbs version
$ rbs list
$ rbs ancestors ::Object
$ rbs methods ::Object
$ rbs method Object then
```
An end user of `rbs` will probably find `rbs prototype` the most useful. This command generates boilerplate signature declarations for ruby files. For example, say you have written the below ruby script.
```ruby
# person.rb
class Person
attr_reader :name
attr_reader :contacts
def initialize(name:)
@name = name
@contacts = []
end
def speak
"I'm #{@name} and I love Ruby!"
end
end
```
Running prototype on the above will automatically generate
```console
$ rbs prototype rb person.rb
class Person
@name: untyped
@contacts: untyped
attr_reader name: untyped
attr_reader contacts: untyped
def initialize: (name: untyped) -> void
def speak: () -> ::String
end
```
It prints signatures for all methods, classes, instance variables, and constants.
This is only a starting point, and you should edit the output to match your signature more accurately.
`rbs prototype` offers three options.
- `rb` generates from just the available Ruby code
- `rbi` generates from Sorbet RBI
- `runtime` generates from runtime API
## Library
There are two important concepts, _environment_ and _definition_.
An _environment_ is a dictionary that keeps track of all declarations. What is the declaration associated with `String` class? An _environment_ will give you the answer.
A _definition_ gives you the detail of the class. What is the type of the return value of `gsub` method of the `String` class? The _definition_ for `String` class knows the list of methods it provides and their types.
The following is a small code to retrieve the definition of the `String#gsub` method.
<!-- run-start:a.rb:bundle exec ruby a.rb -->
```rb
require "rbs"
loader = RBS::EnvironmentLoader.new()
# loader.add(path: Pathname("sig")) # Load .rbs files from `sig` directory
# loader.add(library: "pathname") # Load pathname library
environment = RBS::Environment.from_loader(loader).resolve_type_names
# ::String
string = RBS::TypeName.new(name: :String, namespace: RBS::Namespace.root)
# Class declaration for ::String
decl = environment.class_decls[string]
# Builder provides the translation from `declaration` to `definition`
builder = RBS::DefinitionBuilder.new(env: environment)
# Definition of instance of String
instance = builder.build_instance(string)
# Print the types of `gsub` method:
puts instance.methods[:gsub].method_types.join("\n")
# Outputs =>
# (::Regexp | ::string pattern, ::string replacement) -> ::String
# (::Regexp | ::string pattern, ::Hash[::String, ::String] hash) -> ::String
# (::Regexp | ::string pattern) { (::String match) -> ::_ToS } -> ::String
# (::Regexp | ::string pattern) -> ::Enumerator[::String, self]
# Definition of singleton of String
singleton = builder.build_singleton(string)
# No `gsub` method for String singleton
puts singleton.methods[:gsub]
```
<!-- run-end -->
## Guides
- [Architecture](docs/architecture.md)
- [Core and standard library signature contribution guide](docs/CONTRIBUTING.md)
- [Writing signatures guide](docs/sigs.md)
- [Stdlib signatures guide](docs/stdlib.md)
- [Syntax](docs/syntax.md)
- [RBS by Example](docs/rbs_by_example.md)
- [RBS collection](docs/collection.md)
- [Using `Data` and `Struct`](docs/data_and_struct.md)
- [Releasing a gem with RBS](docs/gem.md)
## Community
Here is a list of some places you can talk with active maintainers.
- [Ruby Discord Server (invite link)](https://discord.gg/ad2acQFtkh) -- We have `rbs` channel in Ruby Discord server.
- [ruby-jp Slack Workspace (in Japanese)](https://ruby-jp.github.io/) -- We have `types` channel in ruby-jp slack workspace.
- [gem_rbs_collection](https://github.com/ruby/gem_rbs_collection) -- We have a repository of third-party RBS type definitions, for the case your dependency doesn't ship with RBS files.
## Development
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec 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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/rbs.
", Assign "at most 3 tags" to the expected json: {"id":"5463","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"