标签: sorbet

为什么“srb tc”没有为我的 RSpec 测试找到“expect”和“eq”方法?

我正在一个实验性开源项目 ( ruby_crystal_codemod ) 中试用 Sorbet 。我无法弄清楚如何让类型检查与嵌套测试项目中的某些 RSpec 测试一起使用。当我运行时srb tc,我看到一些像这样的类型检查错误:

spec/src/example_class_annotated_spec.rb:6: Method it does not exist on T.class_of(<root>) https://srb.help/7003
     6 |  it 'should add @foo and @bar' do
     7 |    instance = ExampleClass.new(2, 3, 4)
     8 |    expect(instance.add).to eq 5
     9 |  end

spec/src/example_class_annotated_spec.rb:8: Method expect does not exist on T.class_of(<root>) https://srb.help/7003
     8 |    expect(instance.add).to eq 5
            ^^^^^^^^^^^^^^^^^^^^
    https://github.com/sorbet/sorbet/tree/67cd17f5168252fdec1ad04839b31fdda8bc6155/rbi/core/kernel.rbi#L2662: Did you mean: Kernel#exec?
    2662 |  def exec(*args); end
            ^^^^^^^^^^^^^^^

spec/src/example_class_annotated_spec.rb:8: Method eq does not exist on T.class_of(<root>) https://srb.help/7003 …
Run Code Online (Sandbox Code Playgroud)

ruby types typechecking sorbet

9
推荐指数
1
解决办法
146
查看次数

Can I specify a duck type in method signatures?

Here's example code:

# typed: true

class KeyGetter

  sig {params(env_var_name: String).returns(KeyGetter)}
  def self.from_env_var(env_var_name)
    return Null.new if env_var_name.nil?

    return new(env_var_name)
  end

  def initialize(env_var_name)
    @env_var_name = env_var_name
  end

  def to_key
    "key from #{@env_var_name}"
  end

  def to_s
    "str from #{@env_var_name}"
  end

  class Null
    def to_key; end
    def to_s; end
  end
end
Run Code Online (Sandbox Code Playgroud)

Running srb tc on it fails with

key_getter.rb:7: Returning value that does not conform to method result type https://srb.help/7005
     7 |    return Null.new if env_var_name.nil?
            ^^^^^^^^^^^^^^^
  Expected KeyGetter
    key_getter.rb:6: Method from_env_var has …
Run Code Online (Sandbox Code Playgroud)

ruby sorbet

8
推荐指数
1
解决办法
152
查看次数

vscode 插件

我正在尝试在 Rails 项目上测试 Sorbet。

  • 遵循收养指南
  • 安装并运行 gem sorbet-rails
  • 变成 # typed: true
  • 重新启动 vscode

但实际上并没有发生任何事情,我想我错过了拼图的一部分。有没有人找到让 Sorbet 与 Vs Code 一起工作的解决方案

谢谢

sorbet

6
推荐指数
1
解决办法
905
查看次数

果汁冰糕要求`sig`作为`attr_reader`

Sorbet正在显示attr_reader的错误,但是请纠正我,如果我错了,则在声明该函数(而不是调用该函数)时需要sig,对吗?

我已经尝试过文档,但我得到的只是这份笔记

注意:许多看起来像局部变量的Ruby构造实际上是没有括号的方法调用!具体来说,请注意attr_reader和零参数方法定义。

app/util/hodor.rb:125: This function does not have a `sig` https://sorbet.org/docs/error-reference#7017
     125 |  attr_reader(:collection_name)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

ruby sorbet

5
推荐指数
2
解决办法
261
查看次数

如何在RSpec模拟中使用冰糕类型检查?

我有一个具有冰糕类型签名定义的方法。尝试在使用RSpec的测试中模拟此方法时,出现类型不匹配错误。我试图了解如何解决此问题并添加基于RSpec的测试而不影响冰糕类型检查。

sig {params(login_context: LoginContext, company_id: String).returns(T::Boolean)}
  def populate_dummy_data(login_context, company_id)
Run Code Online (Sandbox Code Playgroud)

测试代码:

@login_context = double(LoginContext, :requester => @requester) # Creates an instance of type Rspec::Mocks::double
Run Code Online (Sandbox Code Playgroud)

错误:

expected no Exception, got #<TypeError: Parameter ‘login_context’: Expected type LoginContext, got type RSpec::Mocks::Double wit...a_populator_spec.rb:42
Run Code Online (Sandbox Code Playgroud)

ruby unit-testing rspec rspec-mocks sorbet

5
推荐指数
2
解决办法
295
查看次数

使用 Sorbet 时如何重写 Ruby on Rails 中生成的属性方法?

我有一个带有 jsonb 列的模型。此列仅接受 json 对象。Sorbet 正确生成包含以下内容的 .rbi 文件:

module PushedContent::GeneratedAttributeMethods
  sig { returns(T.nilable(T.any(T::Array[T.untyped], T::Boolean, Float, T::Hash[T.untyped, T.untyped], Integer, String))) }
  def value; end

  sig { params(value: T.nilable(T.any(T::Array[T.untyped], T::Boolean, Float, T::Hash[T.untyped, T.untyped], Integer, String))).void }
  def value=(value); end
end
Run Code Online (Sandbox Code Playgroud)

jsonb 列将始终存储数组或哈希值。由于这些方法签名不能满足我的需求,我决定在文件夹下的我自己的文件中覆盖它们:sorbet/rbi/types/app/models/model.rbi

module PushedContent::GeneratedAttributeMethods
  sig { returns(T.nilable(T::Array[T.untyped], T::Hash[T.untyped, T.untyped])) }
  def value; end

  sig { params(value: T.nilable(T::Array[T.untyped], T::Hash[T.untyped, T.untyped])).void }
  def value=(value); end
end
Run Code Online (Sandbox Code Playgroud)

当我运行时,bundle exec rake rails_rbi:models\[Model\]我期望 sorbet 会看到覆盖的方法,并将它们从自动生成的文件中排除。但不幸的是事实并非如此。两个文件中都存在方法。因此,我收到与自动生成的文件相对应的类型错误,而不是与我编写的文件相对应的类型错误。有趣的是,当我运行时srb tc没有错误。

当我从自动生成的文件中删除方法时,类型错误消失了,但显然这不是处理它的最佳方法。

如何覆盖这些方法以便将它们从自动生成的文件中排除?

ruby ruby-on-rails typechecking sorbet

5
推荐指数
0
解决办法
372
查看次数

为什么 Tapioca 生成的 rbi 不包含 Devise current_user 方法?

我正在尝试将 Devise 添加到使用 Sorbet 的 Rails 项目中。添加 Devise 后,我运行bundle exec tapioca dslbundle exec tapioca gem. 现在,在我的控制器上,类型检查抱怨它找不到current_user帮助器方法。

我注意到生成的文件中sorbet/rbi/gems/devise@4.9.2.rbi包含以下描述:

  class << self
    # Define authentication filters and accessor helpers based on mappings.
    # These filters should be used inside the controllers as before_actions,
    # so you can control the scope of the user who should be signed in to
    # access that specific controller/action.
    # Example:
    #
    #   Roles:
    #     User
    #     Admin
    # …
Run Code Online (Sandbox Code Playgroud)

ruby ruby-on-rails sorbet

5
推荐指数
1
解决办法
234
查看次数

你会如何用 Sorbet 做玫瑰记忆?

尝试注释此代码时,rose memoization ( @||=) 给了我一个错误Use of undeclared variable @git_sha

# typed: strict
# frozen_string_literal: true

module Util
  extend T::Sig

  sig { returns(String) }
  def self.git_sha
    @git_sha ||= ENV.fetch(
      'GIT_REV',
      `git rev-parse --verify HEAD 2>&1`
    ).chomp
  end
end
Run Code Online (Sandbox Code Playgroud)

据我发现,我应该声明变量的类型,T.let但还没有弄清楚具体如何。

ruby sorbet

4
推荐指数
1
解决办法
605
查看次数

即使已定义,Sorbet 也无法解析常量

鉴于:

# typed: true

module X
  class Y
  end
end

module X
  class X
    def y
      X::Y
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

冰糕给出错误:

editor.rb:6: Unable to resolve constant Y https://srb.help/5002
     6 |      X::Y
Run Code Online (Sandbox Code Playgroud)

即使定义了 X::Y,为什么 sorbet 也会给出错误?

游乐场链接

ruby sorbet

3
推荐指数
1
解决办法
1147
查看次数

如何指定类型参数

如何使用冰糕指定类型参数?

例如,我想用A返回泛型类型的参数来注释一个方法T[A]

def build_array(value) 
  [value]
end
Run Code Online (Sandbox Code Playgroud)

输出类型取决于输入类型:

build_array(42) #=> return Array[Integer]
build_array('42') #=> return Array[String]
Run Code Online (Sandbox Code Playgroud)

ruby sorbet

2
推荐指数
1
解决办法
628
查看次数

如何在 Sorbet 中为具有属性的散列定义签名?

(请注意,这不能在 sorbet.run 上重现,据我所知,它只能用 Sorbet 的本地副本重现)

我希望我可以使用Typed Structs 功能来创建一个方法签名,其中一个参数是options散列,但这不起作用:

# typed: true
require 'sorbet-runtime'
extend T::Sig

class OptionsStruct < T::Struct
  prop :x, Integer, default: 1
end

sig { params(options: OptionsStruct).void }
def method(options)
  puts options.x
end

# This works
method(OptionsStruct.new({x: 2}))

# This causes the typechecker to throw.
method({x: 2})
Run Code Online (Sandbox Code Playgroud)

本质上,当您键入检查此文件时,它会抱怨在需要 Struct 时传入哈希值。我的问题是:如何为具有特定参数的哈希定义有效签名?结构在这里显然不起作用。虽然我没有尝试过 Shapes,但根据文档,它们非常有限,所以如果可能的话,我宁愿不使用它们。

关于泛型文档提到了哈希,但似乎表明它们只能在哈希的键和值都是相同类型的情况下Hash<Symbol, String>才能使用(例如,要求所有键都是符号,所有值都是字符串),并且不提供任何方式(据我所知)用特定的键定义一个散列。

谢谢!

ruby sorbet

2
推荐指数
1
解决办法
1323
查看次数

Ruby Sorbet 哈希类型检查

我想了解为什么冰糕不抱怨这个例子:例子

sig {params(x: T::Hash[String, String]).void}
def foo(x)
  x.each do |k, v|
    puts "key = #{k}, value = #{v}"
  end
end

hash = {}
hash[1] = 1
foo(hash) #  I'd expect this to fail to type-check
Run Code Online (Sandbox Code Playgroud)

我已声明foo接受 [String, String] 的哈希值,但我传递的是 [Integer, Integer] 的哈希值。我以为冰糕会在这里抱怨......

有没有办法让它在这种情况下出错?

ruby sorbet

1
推荐指数
1
解决办法
943
查看次数

当代码流已经知道 value 不为 nil 时,如何避免使用 Sorbet 的 T.must ?

我在 Rails 项目上使用 Sorbet,并且有一个方法可以对 nilable 属性进行计算。

def age
  return unless dob && dob.year > 1900

  now = Time.now.utc.to_date
  now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
end
Run Code Online (Sandbox Code Playgroud)

在该代码上,dob是nilable。如果我对它进行类型检查,我会收到一堆抱怨,要求将其包装dob在里面T.must(dob)

app/models/person.rb:18: Method year does not exist on NilClass component of T.nilable(Date) https://srb.help/7003
    18 |    return unless dob && dob.year > 1900
                                     ^^^^
  Got T.nilable(Date) originating from:
    app/models/person.rb:18:
    18 |    return unless dob && dob.year > …
Run Code Online (Sandbox Code Playgroud)

ruby ruby-on-rails sorbet

1
推荐指数
1
解决办法
864
查看次数