Rails
正規表現

【Rails】空文字でも許してくれるバリデーションをつくる

「正しいURLか、もしくは空欄ならOK」という

正規表現を設定したときのバリデーションの設定です。


追記

https://railsguides.jp/active_record_validations.html#allow-blank

Active Recordのバリデーション機能には、allow_blankという便利なオプションがあることをコメントで教えていただきました。ありがとうございます。

この記事の存在意義は薄くなりましたが、戒めとして残しておこうと思います。


最初に結論

「正規表現にマッチした値 OR 空文字("")」を通すような

バリデーションを設定したい場合の書き方


app/models/hogehoge.rb

class Hogehoge < ApplicationRecord

VALID_REGEX = /正規表現|\A\z/
validates :fugafuga,
format: { with: VALID_REGEX }
end

なお、schema.rbで該当するカラムのデフォルト値を

default: ""のように設定しておくこと。


やろうとしたこと

スクリーンショット 2019-05-10 19.05.31.png

URLをStrings型で保存する機能を実装しておりまして、

「入力されたURLが正しいかどうか?」をチェックするための

正規表現を使ったバリデーションを設定しようと考えました。


URLにマッチする正規表現でバリデーション

https://www.megasoft.co.jp/mifes/seiki/s310.html

こちらを参考に、モデルにバリデーションを設定します。


app/models/try.rb

# 余計な行は省略

class Try < ApplicationRecord
VALID_URL_REGEX = /https?:\/\/[\w\/:%#\$&\?\(\)~\.=\+\-]+|\A\z/
validates :source_url,
length: { maximum: 255 },
format: { with: VALID_URL_REGEX, message: '正しいURLを入力してください' }
end


rails consoleで挙動を確認してみます。

# 余計な行は省略

$ bin/rails c
Running via Spring preloader in process 93581
Loading development environment (Rails 5.2.3)

[1] pry(main)> try = Try.new=> #<Try:0x00007f9f14fa31c8
id: nil,
source_url: "",
created_at: nil,
updated_at: nil,
>

[2] pry(main)> try.save!
(0.3ms) BEGIN
(0.4ms) ROLLBACK
ActiveRecord::RecordInvalid: バリデーションに失敗しました:

ソースURL 正しいURLを入力してください,

空文字("")は正規表現にマッチせず、バリデーションに失敗しました。

次に、URLとして正しくないものを入力してみます。


[3] pry(main)> try.source_url = 'hogehoge'
=> "hogehoge"

[4] pry(main)> try.save!
(0.3ms) BEGIN
(0.4ms) ROLLBACK
ActiveRecord::RecordInvalid: バリデーションに失敗しました:

ソースURL 正しいURLを入力してください,

意図したとおり、URLとしておかしな文字列はバリデーションに失敗します。

正しいURLを入力してみます。

[5] pry(main)> try.source_url = 'https://qiita.com/'

=> "https://qiita.com/"

[10] pry(main)> try.valid?

=> true

バリデーションを通過しました。

正しく設定できているようです。


空文字でも通過できるようにしたい

しかし、これでは正しいURLの入力が必須になります。邪魔です。

今回は、「URLの入力は任意」にしたいと考えていたため


  1. 何らかの値が入力された場合は、正しいURLかどうかチェック

  2. 何も入力されない場合はチェックしない

このような仕組みにしたいです。


schema.rb

# 余計な行は省略

create_table "tries", force: :cascade do |t|
t.string "source_url", default: "", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end


URLを保存するsource_urlカラムには、NOTNULL制約を設定し

デフォルトの値として空文字("")を入れておりました。

要はこの空文字("")が正規表現にマッチしてくれればいいので、

(正しいURLにマッチする正規表現)|(空文字にマッチする正規表現)

の形に修正しようと考えました。


空文字("")にマッチする正規表現

あれこれ試しましたが、最終的にこちらで成功しました。


app/models/try.rb

  VALID_URL_REGEX = /https?:\/\/[\w\/:%#\$&\?\(\)~\.=\+\-]+|\A\z/



ダメな例


app/models/try.rb

# railsに怒られる

VALID_URL_REGEX = /https?:\/\/[\w\/:%#\$&\?\(\)~\.=\+\-]+|^$/



app/models/try.rb

# hogehogeでもマッチしてしまう

VALID_URL_REGEX = /https?:\/\/[\w\/:%#\$&\?\(\)~\.=\+\-]+|/


さんこう

https://qiita.com/jnchito/items/ea7832df6f64a9034872