[英]rails 5 update attribute only if it's currently nil
Rails 5 中使用 activerecord 更新属性的首选方式是什么,仅当它当前为零时。
car = Car.first
car.connected_at = Time.zone.now
car.save
OR
car = Car.first
car.update!(connected_at: Time.zone.now)
it should update only if car.connected_at is nil
你可以简单地检查#nil?
car = Car.first
car.update_attribute(:connected_at, Time.zone.now) if car.connected_at.nil?
这还不够通用。 我想要 before_validation 之类的东西。我只是不确定哪种方式是首选。
好吧,如果你想进行验证,它看起来像这样..
before_save :validate_connected_at
private
def validate_connected_at
connected_at = connected_at_was if connected_at_changed? && connected_at_was.present?
end
或者
before_save :set_connected_at
private
def set_connected_at
connected_at = Time.zone.now if connected_at.nil?
end
如您所见,更多检查,更多方法。 我肯定会去第一个。
但是,如果您想添加错误消息,那么这就是方法
errors.add(:connected_at, 'Already present!')
那么“#{attr}_was”在 before_save 方法中所有定义的属性上总是可用的?
它们通常可用,而不仅仅是在before_save
,例如在控制台中..
car = Car.first
car.connected_at
=> 'some value'
car.connected_at = 'some other value'
car.connected_at
=> 'some other value'
car.connected_at_was
=> 'some value'
听起来您是在说您想修改特定属性的工作方式,以便它悄悄地忽略您。 我认为你为什么要封闭它的本能是合理的,但如果你多想一想,你可能会认为如果你在很多地方做这种事情,那么使用你的对象会开始变得特别混乱对于不太了解代码的其他人。
也许您想这样做是因为还有其他使用 Car 模型的代码想要建立连接,但并没有真正拥有完整的画面,因此它会尝试您只想在第一次成功的东西。 仅在具有完整图片的类(例如 Car 模型或服务对象)中处理此类操作要好得多。
如果您仍然真的想控制 Car 之外的这种“连接”行为,那么您可以在 Car 类中完全覆盖 attr_writer。 不过,我绝对建议在 before_save 回调上执行此操作。
def connected_at=(new_value)
if @connected_at
raise StandardError, 'connected_at has already been set'
end
@connected_at = new_value
end
无论您尝试分配值的方式如何,这都将起作用。 如果您想知道上面发生了什么,请阅读有关 ruby 中的 attr_accessor 的内容。
这是我对你的问题的理解。
仅当connected_at
nil
汽车才能更新
class Car < ApplicationRecord before_save :updatable? def updatable? connected_at.blank? end end
重点是 before_save 时返回false
。
你可以:
car = Car.first
car.connected_at ||= Time.zone.now
car.save
如果将只分配connected_at
是nil
的false
。
我建议使用before_update
回调并将 OP 的意图重新before_update
为“如果我的属性已经有值,则丢弃更新”。
我想出了这个解决方案(它适用于大量分配,例如Car.update(car_params)
):
before_update :ignore_updates_to_connected_at
def ignore_updates_to_connected_at
return unless connected_at.present? && connected_at_changed?
clear_attribute_change(:connected_at)
end
<attribute_name>_changed?
和clear_attribute_change
方法来自ActiveModel::Dirty 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.