Rails でフォームのテキストフィールドを保存するときに
- 先頭の半角スペース / 全角スペース
- 末尾の半角スペース / 全角スペース
を自動で除去したいという要求があった.
別に Gem を使うまでもなく実現できそうだけど,調べたところ auto_strip_attributes
が良さそうだなーという感じだった.
使ってみた
README に書いてある通り,モデルにフィールドを定義するだけで使えた.簡単!
ただし自動で除去されるのは「半角スペース」だけで「全角スペース」は除去されなかった.
auto_strip_attributes :name
Gem をコードリーディングしてみた
auto_strip_attributes.rb
を見ると86行しかなくて,シンプルな Gem だったので,Ruby の勉強を兼ねてコードリーディングしてみた.
README を見たらわかることも多いけど,自分でコードを読むことも重要!わかったことを簡単にメモしておこうと思う.
1.
Gem のロード時に ActiveRecord に extend してから setup を呼び出していた.
ActiveRecord::Base.send(:extend, AutoStripAttributes) if defined? ActiveRecord AutoStripAttributes::Config.setup
2.
この Gem の正体は指定されたフィールドごとに before_validation
を定義していた.よって変換をした後の状態でモデルのバリデーションが走ることがわかる.
attributes.each do |attribute| before_validation do |record| # (中略) end end
3.
README に書いてある通りだけど,計5種類のデフォルトフィルタが定義されている.
nullify
ってデフォルトで ON なんだなーと思った.
フィルタ名 | デフォルト設定 | 概要 |
---|---|---|
convert_non_breaking_spaces |
OFF | NonBreakingSpace を半角スペースに変換する |
strip |
ON | 先頭と末尾の半角スペースを除去する |
nullify |
ON | .blank? = true な場合自動で nil に変換する |
squish |
OFF | 文字列空白(タブなどを含む)を半角スペースに変換する |
delete_whitespaces |
OFF | 文字列全体の半角スペースとタブを除去する |
4.
上記のデフォルトフィルタ以外に独自フィルタを定義できる.
instance_eval &block if block_given?
5.
README に独自フィルタの例が書いてあるけど,デフォルト設定が false
なら set_filter
にフィルタ名だけを指定することもできる.
:strip_html => false
じゃなくて :strip_html
とも書ける.
AutoStripAttributes::Config.setup do set_filter :strip_html => false do |value| ActionController::Base.helpers.strip_tags value end end
ここを見ると filter.is_a?(Hash)
で分岐していた.
if filter.is_a?(Hash) then filter_name = filter.keys.first filter_enabled = filter.values.first else filter_name = filter filter_enabled = false end
紙でコードリーディング
今回は RubyMine に頼らずに,コードをプリントしてメモしながらコードリーディングしてみた.
SIer 時代によくやったなー!と懐かしさを感じたけど,読みながら頭の中を整理できるし,エディタで読むよりも理解が早かったかも!
(時間使ってないでサクッと読めなんて言わないで!ビギナーだから!笑)
独自フィルタを定義してみた
先頭と末尾の全角スペースを除去するフィルタの需要はあると思うので,本家にプルリクしても良いかなと思ったけど,独自フィルタの機能がせっかくあることだし使ってみた.
config/initializers/auto_strip_attributes.rb
を追加して以下の独自フィルタを書いた.
AutoStripAttributes::Config.setup do set_filter strip_double_byte_space: false do |value| unless value.nil? || !value.is_a?(String) value.gsub(/(^(\s| )+)|((\s| )+$)/, '') end end end
モデル側で strip_double_byte_space: true
を定義するだけで使えるし簡単!
auto_strip_attributes :name, strip_double_byte_space: true
まとめ
- Rails で先頭と末尾の半角スペースを除去したかったら
auto_strip_attributes
を使うと便利! - 先頭と末尾の全角スペースを除去したかったら拡張すれば良し!
- コードをプリントして読んだら理解が早かった!(個人の感想)