我想防止报告distributed
&& checked
均为零||的报告创建后为零。
我还希望用户能够通过以下方式删除现有报告:将表单中的这些值设置为nil或零(创建报告并进行批量编辑,UX倾向于将值设置为0或从表单中删除值而不是“删除”按钮)。
作为一个业余爱好者,这有点不好意思:
class Report < ApplicationRecord
...
before_validation :prevent_meaningless_reports, if: (distributed.nil? || distributed.zero?) && (checked.nil? || checked.zero?)
...
...
private
def prevent_meaningless_reports
if new_record?
throw :abort
else #persisted?
self.destroy
end
end
end
在before_*
回调期间销毁一条记录感到很遗憾。
我冒着问一个潜在的基于意见的问题的风险,因为似乎我可能违反了一些告诉我为什么这是个坏主意的软件原理。
如果这是可以接受的行为,那么最好分两个块来执行,一个用于before_create
(对于新记录),另一个用于before_update
(对于持久记录)?
您将要遇到的问题是,当您尝试更新一个已经不存在的有意义的报告以对其执行进一步的操作时。
例如:
meaningless_report.update(attribute: some_value)
meaningless_report.some_other_value #meaningless_report is already removed from the db and frozen
如果再次尝试更新Meaningless_report对象,则会遇到RuntimeError。因此,这绝对不是一个好主意
一个更好的选择是使用ActiveRecord验证,这样即使在创建报告之前,我们也对它们进行验证以确保它们没有意义,并确保记录在更新期间不会变得毫无意义。>>
例如:
class Report < ApplicationRecord validate :validate_meaningful_reports def not_meaningful_report? (distributed.nil? || distributed.zero?) && (checked.nil? || checked.zero?) end private def validate_meaningful_reports if not_meaningful_report? errors.add(:base, "Report violates validations") end end end
因此,我们确保不会创建无意义的报告。为了处理无意义的旧报告,我们可以为此使用脚本或rake任务。脚本/任务如下所示:
meaningless_reports = Report.unscoped.find_each { |r| r.destroy if r.not_meaningful_report?}
这要安全得多