【问题标题】:Populating single property in Reform在改革中填充单一财产
【发布时间】:2020-02-03 10:24:04
【问题描述】:

我正在使用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

【问题讨论】:

    标签: ruby-on-rails ruby forms rubygems reform


    【解决方案1】:

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

    您要验证interval 的值吗?如果不是,请在Operation 步骤中计算interval,不要涉及reform

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

    • 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"
      
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-07
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多