Rails将类似的before_update回调方法重构/组合成一个

时间:2015-05-06 15:30:48

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

我创建了一些模型回调方法,每次创建,更改或删除文件时都会为某个属性添加时间戳。

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

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

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

在这种情况下,最好保持代码冗长,因为很难看到发生了什么。应该更改回调,以便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作为布尔值进行评估,然后根据此更新或删除时间戳。

相关问题