在 Reform 中填充单个 属性

Populating single property in Reform

我正在使用 Reform gem。假设我有某种形式,我将两个日期作为参数中的两个单独属性传递给该形式。现在在表单中我想实例化另一个名为 interval 的属性(这也是现有的模型属性)来计算这两个日期之间的间隔,然后将其保存到模型中。

# some_form.rb

class SomeForm < Reform::Form
   property: :starts_on
   property: :ends_on
   property: :interval
end

根据传入日期填充间隔、验证它并将其保存在模型中的最佳方法是什么?

我尝试了不同的方法,从覆盖 validate 方法到使用 populator/prepopulator 选项,但都无济于事。

在最好的情况下,我会假设它看起来像这样:

class SomeForm < Reform::Form
   property: :starts_on
   property: :ends_on
   property: :interval, populate: :calculate_interval
end

def calcute_interval
    (starts_on..ends_on).count
end

populatorprepopulator 假设相关属性存在于传入数据中。在你的情况下,interval 不是。

您要验证 interval 值吗?如果不是,则在 Operation 步中计算 interval 并且不涉及 reform.

如果您想要验证,您的选择是:

  • a populator 任一时间戳:

    # some_form.rb
    class SomeForm < Reform::Form
      property :starts_on
      property :ends_on, populator: ->(model:, fragment:, **) do
        self.interval = fragment - starts_on
        self.ends_on = fragment
      end
      property :interval, readable: false
    
      validation do
        required(:starts_on).filled(:time?)
        required(:ends_on).filled(:time?)
        required(:interval).filled(gt?: 2.hours) # or whatever value you like
      end
    end
    
  • 自定义 predicate+rule 组合:

    # some_form.rb
    class SomeForm < Reform::Form
      property :starts_on
      property :ends_on
    
      # NOTE: uses dry-validation v0.13 syntax
      validation do
          configure do
            config.messages_file = "/path/to/your/error_messages.yml"
    
            def gt?(interval, starts_on, ends_on)
              ends_on - starts_on > interval
            end
          end
        end
    
        required(:starts_on).filled(:time?)
        required(:ends_on).filled(:time?)
        rule(ends_on: [:ends_on, :starts_on]) do |ends_on, starts_on|
          ends_on.gt?(starts_on, 2.hours) # or whatever value you like
        end
      end
    end
    
    # error_messages.yml
    en:
      errors:
        rules:
          ends_on:
            gt?: "must be greater than starts_on by %{interval} seconds"