rubyの真偽値の話
rubyではご存知の通りfalseとnil以外は真と評価される。
例えばこういうコードがあったとして
class Project < ActiveRecord::Base def completed? end end
projectsというテーブルにはDATETIME型のcompleted_atというカラムがあったとします。
completed_atにはプロジェクトの完了日時が入り、完了日時が入っていれば完了したと判断できるとしてこのときのProject#completed?の実装はどうしますか?
だいたいこういう選択肢に別れると思います。
1. 実装しない
そもそも単純な話入っていれば終了したとみなせるのだから不要なメソッド。
2. そのままcompleted_atを見る
つまり
def completed? completed_at end
3. completed_atをtrue/falseに変換する
def completed? !!completed_at end
人によって考え方は違うと思うんですが、僕はどう考えても3つ目のtrue/false変換がスジがいいと思うんですよね。
1は程度問題なんですが、ロジックではなくデータを参照しているのが気に入りません。まぁこの程度ならいいかもしれませんが、こういうコード見たことないですか?
- if @project.owner == current_user = link_to '編集'
僕も昔こういうコード書いててこう書いたほうがいいよって言われたことがあります。
- if @project.editable_by?(current_user) = link_to '編集'
2は際どいですが、厳密には真とみなされるオブジェクトとtrueにも違いがあって
true == trueはtrueですが
'anyobject' == trueはfalseです。
その結果、確かrspecのbe_trueとかのマッチャの結果が変わったと思います。
ただ、3に対しても批判があってそのやり方はrubyの仕様的にどうなのっていう意見があります。
そのあたりの議論はここを見ればいいんですがgithub.com
この場では明らかに2のほうがruby的だって言われてます。
うーん、そうなのかなぁ苦笑