【问题标题】:Using ActiveModel::Dirty in Rails Validations在 Rails 验证中使用 ActiveModel::Dirty
【发布时间】:2018-10-06 04:27:38
【问题描述】:

我正在尝试在我的模型验证中使用 Rails ActiveModel::Dirty 来要求存在某些字段,具体取决于我的记录中的 status 曾经或将要是什么。

当前验证

validates :pause_reason, presence: true, if: Proc.new { |o| o.status_will_change! == "Paused" }
validates :unpause_reason, presence: true, if: Proc.new { |o| o.status_was == "Paused"  }

所以pause_reason 验证似乎工作正常,当我将状态更改为Paused 并将pause_reason 留空时,如果我填写上述字段,同样会收到相应的错误“暂停原因不能为空”我没有收到错误。

但是,当我尝试保存相同的更改时,unpause_reason 验证也会显示错误“取消暂停原因不能为空”。我尝试逐步完成 rails 控制台中的步骤,结果如下:

irb(main):026:0> o.status
=> "Open"
irb(main):027:0> o.status = "Paused"
=> "Paused"
irb(main):028:0> o.status_will_change!
=> nil ## should be "Paused" I think
irb(main):029:0> o.status_was
=> "Open"
irb(main):030:0> o.status_was == "Paused"
=> false
irb(main):031:0> o.pause_reason
=> nil
irb(main):032:0> o.valid?
=> true ## should be false 

所以我想我对验证过程中发生的事情感到有点困惑,这会导致pause_reason 验证(看似)按预期工作,但当控制台清楚地显示时,unpause_reason 验证也会失败status_was 等于 "Open"

如果有人可以帮助我了解如何在 Rails 验证中适当地使用 ActiveModel::Dirty,我们将不胜感激。

更新

经过更多研究,我决定将我的“状态验证”组合成一个在update 上验证的方法,如下所示:

validates :status_change_validations, on: :update

def status_change_validations
  if status == "Paused" && pause_reason.blank?
    errors.add(:pause_reason, 'required when pausing an order.')
  elsif status != "Paused" && status_was == "Paused" && unpause_reason.blank?
    errors.add(:unpause_reason, 'required when resuming an order.')
  elsif status == "Canceled" && cancellation_reason.blank?
    errors.add(:cancellation_reason, 'required when canceling an order.')
  elsif status != "Canceled" && status_was == "Canceled" && reopen_reason.blank?
    errors.add(:reopen_reason, 'required when reopening an order.')
  elsif status == "Reactivate" && reactivation_reason.blank?
    errors.add(:reactivation_reason, 'required when reactivating an order.')
  end
end

这似乎完全符合我的意图,但我仍然不确定为什么使用 Procs 的原始单行验证不起作用。如果有人仍然想用一个有效的答案来解释这一点,以加深我对过程和验证的理解,或者提供比我刚刚列出的更好的方法,我会接受你的答案。但这目前有效,所以我将继续使用它。谢谢。

【问题讨论】:

    标签: ruby-on-rails validation ruby-on-rails-5 activemodel


    【解决方案1】:

    方法[attribute]_will_change! 的目的不是显示属性将是什么,而是标记一个类的对象的属性,其中包括ActiveModel::Dirty(在您的情况下,是一个rails 模型类)

    此属性要更改,请在changes属性中记录更改 (ActiveModel::Dirty)

    [attr]_will_change!发送给对象后,[attr]_wasobject.changesActiveModel::Dirty的其他方法可以正确响应。

    所以你的问题结束了,proc 没有问题,但是你使用[attr]_will_change! 的方式。如果我猜对了,你想做的应该是这样的:

    validates :pause_reason, presence: true, if: Proc.new { |o| o.status == "Paused" }
    validates :unpause_reason, presence: true, if: Proc.new { |o| o.status_was == "Paused"  }
    
    

    【讨论】:

      猜你喜欢
      • 2014-05-01
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多