RubyのArrayやHashのリテラルをdeep freezeするshareable_constant_valueマジックコメント
297 views
Post
オブジェクト指向スクリプト言語 Ruby
rubyの標準添付ライブラリであるuriに存在しているURI::MailTo::EMAIL_REGEXP
は、
ある文字列が規格上Emailアドレスとして適切かどうかのチェックに以下のように利用できます。
irb(main):001> require 'uri'
=> true
irb(main):002> URI::MailTo::EMAIL_REGEXP
=> /\A[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/
irb(main):003> URI::MailTo::EMAIL_REGEXP.match?('[email protected]')
=> true
irb(main):004> URI::MailTo::EMAIL_REGEXP.match?('[email protected]')
=> false
irb(main):005> URI::MailTo::EMAIL_REGEXP.match?('[email protected]')
=> false
Railsガイドでも、 このEMAIL_REGEXPを用いてemailのバリデーションを行う方法を以下のように紹介しています。
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }
TechRachoの記事によると、URI::MailTo::EMAIL_REGEXP
の正規表現はHTML規格書から持ってきているため、
URI::MailTo::EMAIL_REGEXP
を使ったバリデーションはブラウザがinput type="email"
で行うバリデーションと一致するというメリットがあります。
URI::MailTo::EMAIL_REGEXP
は、
Rubyリファレンスマニュアルにも
Ruby標準ライブラリリファレンスにも、実は記載されていません。
ですので、URI::MailTo::EMAIL_REGEXP
を利用するのは少々裏技的な側面があるのかもしれません。
ただ、上述の通り、Railsガイドや記事で取り上げられるぐらいに認知されていますので、利用しても大丈夫なのではないかと思います。
概要
Rubyでは、以下のように
shareable_constant_value: literal
というマジックコメントを記入することで、 以下の例のように、定数に代入したArrayやHashのリテラルを深く(deeply)freezeすることが出来ます。少し詳しい話
shareable_constant_value
マジックコメントはRuby 3.0で導入されました。注意点
このマジックコメントのliteralモードでfreezeされるのは定数が対象であるため、 以下のように、代入先が変数である場合にはfreezeされません。
また、このマジックコメントのliteralモードを指定したファイル内では、以下のように、 「freezeされていないオブジェクト」や「freezeされていないものを含むオブジェクト」を定数に代入しようとするとエラーが発生します。
裏を返せば、以下のように、freezeすればエラーが回避できます。 また、freezeする定数とfreezeしない定数でファイルを分けるという自然なアプローチでもエラーを回避できます。
参考文献