LoginSignup
54
51

More than 5 years have passed since last update.

rails 日付や時刻の正当性を validation する

Last updated at Posted at 2014-09-12

やりたいこと

2014-9-31 などを弾きたい。

結論から

ActiveModel::EachValidator を使った Custom Validator を追加します。

gem を使わない理由

  • gem を使わなくても良いくらいの規模。
  • rails のバージョンアップに伴う、gem バージョンアップの負債が増えるのがいやだった。
  • 例えば rails v4.1.5 で validates_timeliness を使うと、以下のような deprecated なエラーが出るようになった。
class MyValidator < ActiveModel::Validator
  def initialize(options={})
    super
    options[:class].send :attr_accessor, :custom_attribute
  end
end
. (called from <class:Miko> at /Users/mikosan/mikosan_no_path/mikofuku.rb:1)
W, [2014-09-12T13:52:35.984731 #6011]  WARN -- : DEPRECATION WARNING: The `Validator#setup` instance method is deprecated and will be removed on Rails 4.2. Do your setup in the constructor instead:

class MyValidator < ActiveModel::Validator
  def initialize(options={})
    super
    options[:class].send :attr_accessor, :custom_attribute
  end
end
. (called from <class:Miko> at /Users/mikosan/mikosan_no_path/mikofuku.rb:1)

書いたもの

日付の正当性をチェックします。
フォーマットは YYYY/MM/DD(例:2014/9/12) に固定します。
※もしフレキシブルにする場合には、4行目や7行目へ適宜手を入れて下さい。

app/validators/date_validator.rb
class DateValidator < ActiveModel::EachValidator

  def validate_each(record, attribute, value)
    record.errors[attribute] << I18n.t('errors.messages.invalid_date_format') unless /\A\d{1,4}\-\d{1,2}\-\d{1,2}\Z/ =~ value

    begin
      (y,m,d) = value.split('-')
      Time.local(y, m, d, 0, 0, 0)
    rescue
      record.errors[attribute] << I18n.t('errors.messages.invalid_date')
    end
  end

end

対応するエラーメッセージを登録します。

config/locales/ja.yml
ja:
  ...
  errors:
    messages:
      invalid_date: の指定が不正です。
      invalid_date_format: の形式が不正です。

呼び出す側は通常の CustomValidator と同じく、

app/models/hoge.rb
class Hoge
  include ActiveModel::Model
  attr_accessor :assigned_date

  validates :assigned_date, date: true

end

などと記述して、Controller 側で valid? することで呼び出せます。

とはいえ...

フォーマットが固定なのは不便ですし、何も考えずにぼーんと日付っぽい文字列を渡して validation してもらいたい気持ちもあるのでその辺りの実装を盛り込んでおきたい気もします。
しかし、そこまでするなら gem にしたほうが良いのでは?とも思います。
ひとまずはここに落ち着きましたが、うーん。

時刻は?

上記日付の validation を流用すれば簡単に作れますので、割愛します。

54
51
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
54
51