首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Sorbet找不到`has_many`关联方法

Sorbet找不到`has_many`关联方法
EN

Stack Overflow用户
提问于 2021-05-26 21:00:29
回答 2查看 155关注 0票数 2

我有一个has_many items的Rails模型

代码语言:javascript
复制
class Plan < ApplicationRecord
  extend T::Sig

  has_many :items, dependent: :destroy

  before_save do
    # hyper simple test method to illustrat problem
    puts items
  end
end

然而,冰沙似乎不能与has_many :items联系起来。当我运行Sorbet类型检查时,我得到以下错误:

代码语言:javascript
复制
$ srb tc
app/models/plan.rb:11: Method items does not exist on T.class_of(Plan) https://srb.help/7003
    11 |    items
            ^^^^^
  Did you mean:
    sorbet/rails-rbi/models/plan.rbi:86: Plan::GeneratedAssociationMethods#items
    86 |  def items; end

对于索贝特的问题,答案是肯定的--我的意思是这种方法。困惑从何而来?为什么RBI文件中的.items定义不能满足Sorbet需要知道这个方法是在哪里定义的?

EN

回答 2

Stack Overflow用户

发布于 2021-05-26 23:11:04

好吧,所以这被证明是对Rails的误解(Ruby?)而不是冰沙。跳过这一点实际上是为了冰激凌,因为它有助于发现和解决这个问题。

问题是,当您将一个块传递给before_save时,调用的是类(Plan),而不是实例(plan)。取而代之的是,一个实例被传入其中。

所以以原始代码为例:

代码语言:javascript
复制
class Plan < ApplicationRecord
  extend T::Sig

  has_many :items, dependent: :destroy

  before_save do
    # hyper simple test method to illustrate problem
    puts items
  end
end

这将导致Plan.before_save(plan)的执行。其中planPlan的实例。因此,在上面的例子中,items被凭空拉出来,不能工作。

两种有效的语法

代码语言:javascript
复制
class Plan < ApplicationRecord
  extend T::Sig

  has_many :items, dependent: :destroy

  before_save do |plan| # <= notice the argument
    puts plan.items
  end
end

都会起作用的。也会是这样:

代码语言:javascript
复制
class Plan < ApplicationRecord
  extend T::Sig

  has_many :items, dependent: :destroy
  before_save :put_items

  def put_items
    puts items
  end
end

我不太确定是什么让第二个魔术发挥作用,是Ruby魔术还是Rails魔术,但有时魔术太多了,我不喜欢。

票数 3
EN

Stack Overflow用户

发布于 2021-07-09 22:12:05

这是因为传递给before_save的proc是在类实例的上下文中运行的,而不是在类本身的上下文中运行,这在默认情况下Sorbet是无法理解的。self为这种情况提供了T.bind,它允许您告诉Sorbet将块中的self视为不同的类型

代码语言:javascript
复制
class Plan < ApplicationRecord
  extend T::Sig

  has_many :items, dependent: :destroy

  before_save do
    T.bind(self, Plan) # treats `self` as `Plan` instead of `T.class_of(Plan)`
    
    # hyper simple test method to illustrate problem
    puts items # type-checks fine
  end
end
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67705439

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档