Rails 5 - 当关系是可选的时,对belongs_to 存在的条件before_save 回调

rmc*_*rry 1 ruby-on-rails callback

我有 2 个模型:

Card belongs_to :template, optional: true
Template has_many :cards
Run Code Online (Sandbox Code Playgroud)

我想向 Card 添加回调:

before_save :set_status, if: self.template.exists?
Run Code Online (Sandbox Code Playgroud)

但这会引发错误,即 Card 类没有方法“模板”?

我也试过:

 before_save :set_status, if: self.attributes.has_key? "template_id"
Run Code Online (Sandbox Code Playgroud)

和:

before_save :set_status, if: self.template.nil?
Run Code Online (Sandbox Code Playgroud)

(这也NoMethodError (undefined method为#`提供了模板'))

和:

before_save :set_status, if: self.template.present?
Run Code Online (Sandbox Code Playgroud)

那么如何检查 Card 是否有模板呢?

编辑

这有效,但为什么这项工作有效而上述无效?似乎 self.template 必须在方法调用中。

before_save :set_status, if: :template_exists?

def template_exists?
  return !self.template.nil?
end
Run Code Online (Sandbox Code Playgroud)

Ada*_*man 5

before_save :set_status, if: :template_exists?

def template_exists?   
  return !self.template.nil? 
end
Run Code Online (Sandbox Code Playgroud)

^ 此方法有效,因为回调需要可以在运行时执行的代码。您可以向它传递一个映射到方法名称的符号或字符串,或者您可以向它传递一个它可以在运行时执行的 proc 或 lambda。但是如果你通过它的代码像

before_save :set_status, if: self.template.nil?
Run Code Online (Sandbox Code Playgroud)

那么它实际上会在您设置回调时尝试执行该代码,而不是在调用回调时执行该代码。当您设置回调时,self指的是类Card而不是类的实例。

如果您想了解更多细节,这里有一些关于ActiveRecord 回调的文档。