定义元动态创建方法的方法类型

时间:2019-07-15 06:56:18

标签: sorbet

我正在使用<form [formGroup] = "configuracion" (ngSubmit)="onSubmit()"> <div class="row" id="ConfigFacturacion"> <!-- COL 1 --> <div class="col px-4"> <form formGroupName="configPT"> <input type="text" formControlName="prubA"> </form> </div> <!-- COL 2 --> <div class="col px-4"> <form formGroupName="configVS"> <input type="text" formControlName="prubB"> </form> </div> </div> </form> ,我真的很想能够键入为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))

哪个有效 ,但不是很漂亮。有没有更好的方法可以解决这个问题?

2 个答案:

答案 0 :(得分: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 ...

答案 1 :(得分:0)

  

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

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

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

  • const保留不变的参数
  • prop用于可能更改的参数
  • 在没有给出值的情况下,使用default提供默认值
  • 对可能为nil的参数使用T.nilable类型

在香草T :: Struct的基础上,我还添加了对“ maybe”的支持,这是对args的支持,它实际上是可选的,可以为nil。 IE:如果没有传递值,则完全不应该使用它。它与使用nil作为默认值有所不同,因为当传入一个值时,它可以是nil。如果您对此“也许”组件感兴趣,请随时与我联系。