Rails: beforeバリデーションをやめてセッターメソッドにしよう(翻訳)
以下のようなコードは多くのプロジェクトで目にします。
class Something
before_validation :strip_title
def strip_title
self.title = title.strip
end
end
しかし、この要件を満たす書き方は他にもあるのです。
class Something
def title=(val)
@title = val.strip
end
end
あるいは以下のようにも書けます。
class Something
def title=(val)
self['title'] = val.strip
end
end
.あるいは以下のようにも。
class Something
def title=(val)
super(val.strip)
end
end
クラス内でのデータ保持方法に応じたものを選べばよいのです。さまざまなgemでさまざまな方法が使われています。
私がこの書き方を好む理由は以下のとおりです。
val
がnil
の場合にコケる: はい、私はこれをよいことだと思っています。自分たちのフロントエンド側からnil
がタイトルとして送信されることなどめったにないので、たまたまnil
になったときに何かがコケて例外を発するのは問題ありません。いずれにしろこんなことはまず起こりません。私のプログラマーとしてのトカゲ脳はひととおりのエッジケースを察知していますし、私のトカゲ脳のこういうところが大好きです。しかしこのトカゲ脳がごくまれに私を裏切って、まず起こりえないようなエッジケースに注目してしまうことがあります。- マジックを減らせる: Railsバリデーションのコールバックはクールですし、何度となく使ってきました。だからといって、スペースを取り除くのにわざわざコールバックを持ち出す必要はありません。
- 適用範囲が広い: フィールドに値を設定した後にフィールドを読み出せば、途中で
save
しなくても反映されます。バリデーションを(何らかの理由で)実行せずにsave
した場合も同様です。
something.code = " 123 "
something.code
# => 123
something.save(validate: false)
私は、Command ObjectやForm Objectといった境界を超える用途に使われるオブジェクトに対して、バリデーションを消し去るルールを挿入する手法が特に気に入っています。
まとめ
以上で、ささやかなレッスンはすべて終了です。もっとお知りになりたい方は、元記事末尾のメーリングリストに加入いただくか、私どものFearless Refactoringの購入をぜひお願いします。
概要
原著者の許諾を得て翻訳・公開いたします。