如何创建自定义验证器以拒绝持续时间< 10分钟

时间:2016-09-26 22:35:25

标签: ruby-on-rails ruby validation time

我有一个有氧运动模型,持续时间为#34;时间数据类型的字段(Rails 4.2.6 / Ruby 2.2.4应用程序)。我需要帮助对自定义验证器进行故障排除,以防止用户保存持续时间少于10分钟的有氧运动。

这是我的_form.html.erb中的相关字段:   

<%= f.input :duration do %> <br>
<%= f.time_select :duration, :include_blank => true, include_seconds: true %>
<% end %>

这是我在/app/validators/duration_exceeds_ten_min_validator.rb中的自定义验证器

class DurationExceedsTenMinValidator < ActiveModel::EachValidator

    def validate_each(record, attribute, value)
          unless duration_exceeds_ten_min
          record.errors[attribute] << "must be at least 10 min"
        end
     end

  private

# Check if duration is greater than or equal to 10 minutes, a.k.a. duration_exceeds_ten_min
# If that's the case, return true, otherwise false.

  def duration_exceeds_ten_min
    if Time.parse(self.duration.strftime("%H:%M:%S") < "00:10:00")
      return false
    else
      return true
    end
  end
end

在我的cardio_exercise模型(cardio_exercise.rb)中,我补充说:

validates :duration, duration_exceeds_ten_min: true

代码执行时,会抛出以下错误:

 undefined method `duration' for #<DurationExceedsTenMinValidator:0x0000000ef5c4c8>

当我&#34;强迫&#34;在真或假条件下,自定义验证器似乎正常工作。我的if语句有问题。我被卡住了;我无法弄清楚如何正确设置条件。如何修复自定义验证器?我感谢任何帮助&amp;咨询!

2 个答案:

答案 0 :(得分:1)

只需将时间转换为秒,让ActiveSupport :: Duration完成工作。

 def validate_each(record, attribute, value)
   if value.to_i.seconds < 10.minutes
     record.errors[attribute] << "must be at least 10 min"
   end
 end

如果您对您的方法无效的原因感兴趣,因为您在验证程序中使用self.duration。在此上下文中self是验证器 - 而不是模型。

答案 1 :(得分:0)

我的自定义验证程序的问题是由于我未能在time_select HTML中包含“ignore_date”选项。

在查看我的源代码时,我注意到日期值包含在用户输入的时间值中。由于这些“隐藏字段”,自定义验证器失败。 Ruby on Rails文档说明:“此方法[time_select]还将为实际的年,月和日生成3个输入隐藏标记,除非选项:ignore_date设置为true。”

在我的HTML中将选项“:ignore_date设置为true”后,我的自定义验证器按预期工作。 HTML中的这一变化解决了这个问题。用户不能再保存不到10分钟的有氧运动。我希望将来这对其他人来说是有用的信息。

我赞赏@max帮助我改进自定义验证器,并解释为什么验证器中“self”的位置与模型相比无效。