開発備忘録 2018/10/10

Ruby の case 文

Ruby の case 文、ぶっちゃけ「他の言語でいう switch 文のことでしょ?」という認識だったが、甘かった。
Ruby の case 文は他の言語の switch 文よりかなり自由度が高い。

例えばこういうことができる。

def valid_status?(status)
  case status
  when error_code? then false
  else true
  end
end

def error_code?
  ->(status)  { !(200...300).include?(status) }
end

when に Proc を渡すことができる。

Ruby は whenで受け取ったものを === で評価するらしい。そして === はメソッドなので、オブジェクトによって挙動が変わる。

今回の Proc の場合でいうと、Proc#===Proc#call のようにブロックを呼び出してくれるので、when に Proc を指定することができるという訳だ。

奥深い。

Rails Way な日付のフォーマット

日付のフォーマットというと決まって自分はこれだった。

Time.zone.now.strftime('%Y-%m-%d')

ただこれだと '%Y-%m-%d'マジックナンバーなので、他のところで同じコードを書きたくなったときにつらい。
そこで Rails だと config/initializers/time_formats.rb を作成し、フォーマットを共通化する。

Time::DATE_FORMATS[:date_hyphen] = '%Y-%m%d'

これにより最初のコードがこう書けるようになる。

Time.zone.now.to_s(:date_hyphen)

うん、こっちの方が断然良い。

init(frame:) と init(coder:) と awakeFromNib() の違い

はい、唐突に iOS の話をします。

カスタム View の初期化処理を書こうとしたときにふとこんなことを思った。

「あれ、初期化処理てどこに書いたらいいんだ……?」

Xcode のテンプレートファイルにもれなく付いてくる init(frame:) やら awakeFromNib()、今まで何となくスルーしてたけど、ちょっと困ってしまったので違いについて調べてみた。

init(frame:)

自分で frame を指定して View をつくる、つまりコードから init する場合に必要

init(coder:)

storyboard や nib から init する場合に必要

awakeFromNib()

super.awakeFromNib() が呼ばれたとき、IBOutlet や IBAction の初期化が保証される。
ちなみに init(coder:) の時点では outlet や action はロードされていないので、順序的には init(coder:) -> awakeFromNib() という感じになる。

init の説明がドキュメントを読んだだけではイマイチ理解できず、いろんな人の記事を漁った。 Apple のドキュメント、もう少し直接的な言い方で分かりやすく書いてくれないかなぁ……。