【问题标题】:Sorbet: how do you add a signature for a dynamically generated method?Sorbet:如何为动态生成的方法添加签名?
【发布时间】:2019-09-24 20:09:07
【问题描述】:

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

这是它的管理器的样子:

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 上还没有这样做。可能是出于同样的原因。

【问题讨论】:

    标签: sorbet


    【解决方案1】:

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

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

    【讨论】:

    • 我没有意识到您可以将 .rbis 放在 .rbs 旁边。这是个好主意。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2019-11-04
      • 1970-01-01
      • 2011-05-26
      • 1970-01-01
      • 2023-03-10
      • 2011-02-03
      • 1970-01-01
      • 1970-01-01
      • 2010-11-20
      相关资源
      最近更新 更多