RBS é uma linguagem para descrever a estrutura de programas Ruby. Você pode anotar a definição de uma classe ou módulo: métodos definidos na classe, variáveis de instância e seus tipos e relações de herança/combinação. Também permite declarar constantes e variáveis globais.
A seguir está um pequeno exemplo de RBS para um aplicativo de bate-papo.
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
3.2
em 2023.)>= 3.0
em 2023.) Instale a gema rbs
. $ gem install rbs
na linha de comando ou adicione uma linha em seu Gemfile
.
gem "rbs"
A gem vem com a ferramenta de linha de comando rbs
para demonstrar o que ela pode fazer e ajudar a desenvolver o RBS.
$ rbs version
$ rbs list
$ rbs ancestors ::Object
$ rbs methods ::Object
$ rbs method Object then
Um usuário final do rbs
provavelmente achará rbs prototype
o mais útil. Este comando gera declarações de assinatura padronizadas para arquivos Ruby. Por exemplo, digamos que você escreveu o script Ruby abaixo.
# 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
A execução do protótipo acima irá gerar automaticamente
$ 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
Imprime assinaturas para todos os métodos, classes, variáveis de instância e constantes. Este é apenas um ponto de partida e você deve editar a saída para corresponder à sua assinatura com mais precisão.
rbs prototype
oferece três opções.
rb
gera apenas a partir do código Ruby disponívelrbi
gera a partir do Sorbet RBIruntime
gera a partir da API de tempo de execução Existem dois conceitos importantes, ambiente e definição .
Um ambiente é um dicionário que controla todas as declarações. Qual é a declaração associada à classe String
? Um ambiente lhe dará a resposta.
Uma definição fornece os detalhes da classe. Qual é o tipo de valor de retorno do método gsub
da classe String
? A definição da classe String
conhece a lista de métodos que ela fornece e seus tipos.
A seguir está um pequeno código para recuperar a definição do método String#gsub
.
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 ]
Data
e Struct
Aqui está uma lista de alguns lugares onde você pode conversar com mantenedores ativos.
rbs
no servidor Ruby Discord.types
de canal no ruby-jp slack workspace. Depois de verificar o repositório, execute bin/setup
para instalar as dependências. Em seguida, execute bundle exec rake test
para executar os testes. Você também pode executar bin/console
para obter um prompt interativo que permitirá experimentar.
Para instalar esta jóia em sua máquina local, execute bundle exec rake install
. Para lançar uma nova versão, atualize o número da versão em version.rb
e, em seguida, execute bundle exec rake release
, que criará uma tag git para a versão, enviará commits e tags git e enviará o arquivo .gem
para rubygems.org.
Relatórios de bugs e solicitações pull são bem-vindos no GitHub em https://github.com/ruby/rbs.