0

我正在使用graphql-ruby,我真的很希望能够键入为之类的东西创建的动态方法arguments

小例子:

class Test

  argument :first_argument, String
  argument :secondArgument, String, as: second_argument, required: false

  def method
    puts first_argument.length # this is okay
    puts second_argument.length # this is a problem, because it can be nil
  end
end

我试图通过这样做来定义这些:

  # ...
  first_argument = T.let(nil, String)
  second_argument = T.let(nil, T.nilable(String))

这似乎不起作用。我也做过

  #...
  sig { returns(String) }
  def first_argument; ""; end
  sig { returns(T.nilable(String)) }
  def second_argument; end

有效,但并不过分漂亮。有没有更好的方法来解决这个问题?

4

2 回答 2

1

对于元编程声明的键入方法有一些新生的实验性支持,如下所示:https ://sorbet.org/docs/metaprogramming-plugins

在这种情况下,您可以定义一个插件文件,如:

# argument_plugin.rb

# Sorbet calls this plugin with command line arguments similar to the following:
# ruby --class Test --method argument --source "argument :first_argument, String"
# we only care about the source here, so we use ARGV[5]
source = ARGV[5]
/argument[( ]:([^,]*?), ([^,]*?)[) ]/.match(source) do |match_data|
  puts "sig {return(#{match_data[2]})}" # writes a sig that returns the type
  puts "def #{match_data[1]}; end"      # writes an empty method with the right name
end

我在这里只包含了参数的“getter”,但是继续写出 setter 方法的 sig 应该很简单。您还想处理该argument方法的所有变体,因为我只处理了带Symbol, Type参数的变体。对于它的价值,我不确定传递给你的插件的“源”是否会用括号进行标准化,所以我也做了正则表达式匹配。我还怀疑如果您将符号名称作为变量而不是文字传递,这将不起作用。

然后我们使用 YAML 文件告诉 Sorbet 这个插件。

# triggers.yaml

ruby_extra_args:
  # These options are forwarded to Ruby
  - '--disable-gems' # This option speeds up Ruby boot time. Use it if you don't need gems
triggers:
  argument: argument_plugin.rb # This tells Sorbet to run argument.rb when it sees a call to `argument`

运行 Sorbet 并传入 yaml 配置文件作为参数--dsl-plugins

❯ srb tc --dsl-plugins triggers.yaml ... files to type check ...
于 2019-07-22T15:32:16.447 回答
0

我真的很希望能够输入为诸如参数之类的东西创建的动态方法

Sorbet 不支持键入这样的动态方法。但它们确实提供了一个T::Struct具有类似功能的类。上周我为我的项目做了类似的事情,我将在下面描述我做了什么。如果T::Struct对您不起作用,另一种方法是编写一些代码来生成您手动编写的 Sig。

我的方法是T::Struct用作“参数”类的包装器。您可以将 args 定义为 props,T::Struct如下所示:

  • const对于不变的论点
  • prop对于可能改变的论点
  • 用于default在未给出值时提供默认值
  • T.nilable对可以为 nil 的参数使用类型

在 vanilla T::Struct 的基础上,我还添加了对“maybe”的支持,这是对真正可选且可以为 nil 的 args 的支持。IE:当一个值没有传入时,根本不应该使用它。它与nil用作默认值不同,因为当传入一个值时,它可以是nil. 如果您对这个“可能”组件感兴趣,请随时 DM 我。

于 2019-07-15T15:13:55.287 回答