【问题标题】:Rails refactor/combine similar before_update callback methods into oneRails 将类似的 before_update 回调方法重构/合并为一个
【发布时间】:2015-07-16 20:30:40
【问题描述】:

我创建了一些模型回调方法,这些方法可以在每次创建、更改或删除文件时为属性添加时间戳。

我想知道是否有更优雅的方式来编写这些回调,而不必重复类似的方法代码五次:

before_update :quote_file_updated?, on: [:create, :update], if: ->(r) { r.quote_file_changed? }
before_update :survey_file_updated?, on: [:create, :update], if: ->(r) { r.survey_file_changed? }
before_update :sign_off_sheet_file_updated?, on: [:create, :update], if: ->(r) { r.sign_off_sheet_file_changed? }
before_update :invoice_file_updated?, on: [:create, :update], if: ->(r) { r.invoice_file_changed? }
before_update :cert_file_updated?, on: [:create, :update], if: ->(r) { r.cert_file_changed? }


def quote_file_updated?
  self.remove_quote_file ? self.quote_file_date = nil : self.quote_file_date = Time.now
end

def survey_file_updated?
  self.remove_survey_file ? self.survey_file_date = nil : self.survey_file_date = Time.now
end

def sign_off_sheet_file_updated?
  self.remove_sign_off_sheet_file ? self.sign_off_sheet_file_date = nil : self.sign_off_sheet_file_date = Time.now
end

def invoice_file_updated?
  self.remove_invoice_file ? self.invoice_file_date = nil : self.invoice_file_date = Time.now
end

def cert_file_updated?
  self.remove_cert_file ? self.cert_file_date = nil : self.cert_file_date = Time.now
end

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 methods callback


    【解决方案1】:
    before_update :set_updated_fields, on: [:create, :update]
    
    def set_updated_fields
      ["quote", "survey", "sign_off_sheet", "invoice", "cert"].each do |filetype|
        if self.send("#{filetype}_file_changed?")
          self.attributes = {"#{filetype}_file_date" => self.send("remove_#{filetype}_file") ? nil : Time.now}
        end
      end
    end
    

    这有点难以理解,但我认为它会起作用。

    【讨论】:

    • 我在原始代码中犯了一个错误,其中 quote_file_changed? 对每个回调都重复了。抱歉,现在更新了。我如何重构您的答案以反映变化?
    • 好的,等一下。我认为它们应该是survey_file.changed?sign_off_sheet_file_changed? 等?
    • 谢谢!当我创建和删除文件时它工作得很好,但当我用新值更新文件时就不行了。
    • 进行一些登录以查看关联文件(我们正在使用 `"#{filetype}_file_changed?" 进行测试。有时使用代理关联,对象可以在内存中拥有关联的对象而不是“注意到”它在数据库中发生了变化。
    • 啊,明白了!当我得到答案时会调查并发布答案。感谢您的帮助。
    【解决方案2】:

    在这种情况下最好保持代码冗长,因为很难看到发生了什么。应该更改回调,以便 before_update 变为 before_save(因此它也会在创建操作时触发)。

    回调应该是:

    before_save :quote_file_updated?, if: ->(r) { r.quote_file_changed? or r.remove_quote_file.to_b }
    

    to_b 是一种将01remove_quote_file 转换为布尔值的方法。基于此,我们可以在文件被删除时将日期戳设置为nil

    方法本身应该变成:

    def quote_file_updated?
      remove_quote_file.to_b ? self.quote_file_date = nil : self.quote_file_date = Time.now
    end
    

    我们再次将remove_quote_file 评估为布尔值,然后根据此更新或删除时间戳。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-20
      • 2021-07-16
      相关资源
      最近更新 更多