首页 > 解决方案 > 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自动生成。

为了实际使用活动标志,我在我的模型中执行此操作:

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一旦定义就会返回的最好方法是什么,最好不要手动更改自动生成的文件?

顺便提一句。我试图查看enumRails 中的类型是如何处理的……看起来还没有完成sorbet-typed。可能出于同样的原因。

标签: sorbet

解决方案


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

至于枚举,Sorbet 本身并不支持枚举文字类型,所以这可能就是原因。


推荐阅读