Sorbet:如何为动态生成的方法添加签名?

时间:2019-09-24 20:09:07

标签: sorbet

我正在使用https://github.com/kenn/active_flaghttps://github.com/chanzuckerberg/sorbet-rails

这是其rbi的样子:

module ActiveFlag
  extend ActiveSupport::Concern
end
class ActiveFlag::Definition
  def column; end
  def human(key, options = nil); end
  def humans; end
  def initialize(column, keys, klass); end
  def keys; end
  def maps; end
  def pairs; end
  def set_all!(key); end
  def to_array(integer); end
  def to_i(arg); end
  def to_value(instance, integer); end
  def unset_all!(key); end
end
class ActiveFlag::Railtie < Rails::Railtie
end
class ActiveFlag::Value < Set
  def method_missing(symbol, *args, &block); end
  def raw; end
  def set!(key, options = nil); end
  def set(key); end
  def set?(key); end
  def to_human; end
  def to_s; end
  def unset!(key, options = nil); end
  def unset(key); end
  def unset?(key); end
  def with(instance, definition); end
end
module ActiveFlag::ClassMethods
  def flag(column, keys); end
end
class ActiveRecord::Base
  extend ActiveFlag::ClassMethods
end

我添加的最后一位(扩展了AR :: Base),其余srb rbi gems是自动生成的。

要实际使用Active Flag,我需要在模型中执行以下操作:

flag :visible_to, [:employee, :manager, :admin]

visible_to是一个整数列。 Sorbet Rails已经输入了它:

  sig { returns(Integer) }
  def visible_to; end

  sig { params(value: Integer).void }
  def visible_to=(value); end

  sig { returns(T::Boolean) }
  def visible_to?; end

可以更改此定义,但这是一个自动生成的文件,我认为更改将丢失。所以我接下来尝试的是在使用该方法的位置正上方添加一个sig:

  sig { returns(ActiveFlag::Value) }
  def visible_to; end
  flag :visible_to, [:employee, :manager, :admin]

这里的问题是Sorbet失败,因为我“定义”的方法未返回任何内容。我知道这很好,因为在调用flag时会被覆盖(它在内部使用define_method),但是我不知道如何将此信息传达给Sorbet。

Returning value that does not conform to method result type https://srb.help/7005
    54 |  def visible_to; end
          ^^^^^^^^^^^^^^^^^^^
  Expected ActiveFlag::Value
    Method visible_to has return type ActiveFlag::Value
    54 |  def visible_to; end
          ^^^^^^^^^^^^^^
  Got NilClass originating from:
    54 |  def visible_to; e

所以我的问题是。告诉Sorbet最好的方法是,一旦定义,此方法将返回ActiveFlag::Value,理想情况下无需手动更改自动生成的文件?

顺便说一句。我试图查看Rails中enum的类型是如何处理的……看起来好像还没有在sorbet-typed上完成过。可能是出于相同的原因。

2 个答案:

答案 0 :(得分:2)

当您要覆盖生成的rbi文件时,可以为工作空间中的同一类创建第二个rbi文件,并在其中移动方法。 Sorbet将为您处理合并多个定义文件。我们将这些文件保存在生成​​文件旁边的单独sorbet/custom目录中;其他人将rbi文件放在其应用程序目录中的rb文件旁边。

对于枚举,Sorbet本身不支持枚举文字类型,因此可能是原因。

答案 1 :(得分:0)

您可以为sorbet-rails实现一个自定义插件,以生成active_flag添加的方法,并删除错误生成的信号。这是它的文档:

https://github.com/chanzuckerberg/sorbet-rails/blob/master/README.md#extending-model-generation-task-with-custom-plugins