【问题标题】:Rals 5.2 - how to set conditions on included for a module?Rals 5.2 - 如何为模块设置条件?
【发布时间】:2019-10-29 05:15:11
【问题描述】:

我有(我认为)this question 的反面。

我有一个通常包含在某些 ActiveRecord 模型中的模块 (ActiveConcern):

module IntegrityScoring
  extend ActiveSupport::Concern

  included do
    before_save :calculate_score, if: :has_changes_to_save?
  end

  def calculate_score
    # do some work
  end
end

现在我正在编写一个需要调用这个 calculate_score 的 rake 任务:

  task seed_weights: :environment do    
    include IntegrityScoring # * this line throws an error *

    Contact.all.each do |contact|
      contact.score = contact.calculate_score
      contact.save
    end
  end

抛出的错误是:

undefined method `before_save' for Object:Class

在 rake 任务的上下文中,before_save 回调没有意义(实际上会抛出错误,因为该方法在这里不存在,因为它不是 ActiveRecord 模型,只是 PORO)。

显然我可以从模块中删除included 代码并将before_save 回调添加到包含该模块的每个类。

但我希望更简单的解决方案是向included 添加一个条件,以便将 before_save 仅添加到 ActiveRecord 模型中。这甚至可能吗...类似于:

  included 'only if including class is type of ActiveRecord' do
    before_save :calculate_score, if: :has_changes_to_save?
  end

【问题讨论】:

    标签: ruby-on-rails activerecord module rake mixins


    【解决方案1】:

    我认为你应该能够跳过回调

    Contact.skip_callback(:save, :before, : calculate_score, raise: false))
    

    【讨论】:

    • 谢谢,但我不希望 Contact 类本身跳过回调。我希望 Rake 任务跳过它。问题是,当 rake 任务命中“包含”行时,Rails 崩溃并出现 Object::Class 上不存在“before_save”的错误 - 因为显然 Rake 任务只是一个 PORO 而不是 ActiveRecord 类。
    • 啊,好吧,我误解了那部分。但是我看到您正在调用contact.calculate_score 为什么需要包括IntegrityScoring?据我所知,这没有任何意义。您没有在 rake 任务的上下文中调用 calculate_score。
    • 天啊,周五下午 5 点,我好蠢。请将其添加为答案!
    • 有时一双新鲜的眼睛会有所帮助;)。
    【解决方案2】:

    您在联系上下文中调用calculate_score,不需要IntegretyScoring。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-16
      • 1970-01-01
      • 2021-08-30
      • 1970-01-01
      • 1970-01-01
      • 2017-09-14
      • 1970-01-01
      相关资源
      最近更新 更多