Vin*_*cha 1 ruby ruby-on-rails sorbet
我在 Rails 项目上使用 Sorbet,并且有一个方法可以对 nilable 属性进行计算。
def age
return unless dob && dob.year > 1900
now = Time.now.utc.to_date
now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
end
Run Code Online (Sandbox Code Playgroud)
在该代码上,dob是nilable。如果我对它进行类型检查,我会收到一堆抱怨,要求将其包装dob在里面T.must(dob):
app/models/person.rb:18: Method year does not exist on NilClass component of T.nilable(Date) https://srb.help/7003
18 | return unless dob && dob.year > 1900
^^^^
Got T.nilable(Date) originating from:
app/models/person.rb:18:
18 | return unless dob && dob.year > 1900
^^^
Autocorrect: Use `-a` to autocorrect
app/models/person.rb:18: Replace with T.must(dob)
18 | return unless dob && dob.year > 1900
^^^
app/models/person.rb:21: Method year does not exist on NilClass component of T.nilable(Date) https://srb.help/7003
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
^^^^
Got T.nilable(Date) originating from:
app/models/person.rb:21:
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
^^^
Autocorrect: Use `-a` to autocorrect
app/models/person.rb:21: Replace with T.must(dob)
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
^^^
app/models/person.rb:21: Method month does not exist on NilClass component of T.nilable(Date) https://srb.help/7003
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
^^^^^
Got T.nilable(Date) originating from:
app/models/person.rb:21:
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
^^^
Autocorrect: Use `-a` to autocorrect
app/models/person.rb:21: Replace with T.must(dob)
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
^^^
app/models/person.rb:21: Method month does not exist on NilClass component of T.nilable(Date) https://srb.help/7003
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
^^^^^
Got T.nilable(Date) originating from:
app/models/person.rb:21:
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
^^^
Autocorrect: Use `-a` to autocorrect
app/models/person.rb:21: Replace with T.must(dob)
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
^^^
app/models/person.rb:21: Method day does not exist on NilClass component of T.nilable(Date) https://srb.help/7003
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
^^^
Got T.nilable(Date) originating from:
app/models/person.rb:21:
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
^^^
Autocorrect: Use `-a` to autocorrect
app/models/person.rb:21: Replace with T.must(dob)
21 | now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
Run Code Online (Sandbox Code Playgroud)
告诉冰糕这dob不会是零的最好方法是什么,因为如果是的话我已经回来了。
这是 Sorbet 最常见的问题,它出现在Sorbet 常见问题解答页面的顶部。
\n简短的答案是,您需要分配dob给一个变量(尽管没有任何括号,但dob实际上是对此上下文中的方法的调用,因为在此范围内尚未对调用的变量进行分配dob)。
dob = self.dob对于您的情况,最简单的解决方法是在方法的顶部编写,该dob方法调用该方法一次并将其分配给一个变量:
def age\n dob = self.dob\n return unless dob && dob.year > 1900\n\n now = Time.now.utc.to_date\n now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)\nend\nRun Code Online (Sandbox Code Playgroud)\n\xe2\x86\x92 查看 sorbet.run 上的完整示例
\n第一次赋值后的所有引用dob现在都是从局部变量读取,而不是调用方法,这允许 Sorbet 记住它执行的任何流敏感类型分析。