Virtus:将空数组与未设置的属性区分开来

mig*_*igu 5 ruby ruby-on-rails

我有几个提交给 Virtus 对象的表单(通过控制器)。有些表单包含extras属性,有些则不包含。

我目前无法区分是否extras已设置为空数组(即用户取消选择表单上的所有复选框)或是否从未提交过附加内容。在任何一种情况下,extras都将是一个空数组。

我需要这种区别,因为如果用户取消选择所有extras我需要更新它们。另一方面,如果额外内容不是表单的一部分(即不在参数中),我不应该更新它们。

class UpdateForm
  include Virtus.model(nullify_blank: true)
  include ActiveModel::Model
  attribute :extras, Array
  attribute :booking_time, Time

  def save
    updatable_attributes = self.attributes.delete_if { |key, value| value.blank? }
    some_object.update(updatable_attributes)
  end
end
Run Code Online (Sandbox Code Playgroud)

extras如果我这样称呼它,我怎么能让 Virtus 给我一个零:

UpdateForm.new(booking_time: Time.current)
Run Code Online (Sandbox Code Playgroud)

或者有没有更好的模式来做到这一点?

Kir*_*kov 3

默认情况下,@extras属性将被设置为空数组(即使您添加 default: nil到该属性)。
您可以做的是覆盖初始值设定项,以便除非实际定义它,否则它将设置@extras为。 并使用which而不是在空数组上返回 true 。nil
#nil?#blank?

class UpdateForm
  include Virtus.model(nullify_blank: true)
  include ActiveModel::Model
  attribute :extras, Array
  attribute :booking_time, Time

  def initialize(opts={})
    super
    @extras = nil unless (opts[:extras] || opts['extras'])
  end

  def save
    updatable_attributes = self.attributes.delete_if { |key, value| value.nil? }
    some_object.update(updatable_attributes)
  end
end
Run Code Online (Sandbox Code Playgroud)