【Rails】コードを読んでみる blank?編

2019年7月30日Ruby

こんにちは、しきゆらです。
今回は、最近意図的に行っている「良いといわれているライブラリのコードを読む」一環として、
Ruby on Railsの便利メソッドの一つ「blank?」の定義を見てみます。

 

なぜこんなことしているの???

私は、これまでライブラリ等を使わずに自分であれこれコードを書いてきました。
しかし、自分の中でいいコーディングの方法が確立できているわけではないので、設計や記述が悪くスクラップ&ビルド状態でうまく作り続けることができませんでした。

そんな中、先輩から「一般的に良いといわれているコードに触れておくと勉強になる」ということを伺い、実践してみようと思い立ったわけです。
読む者は、良く触れるものであれば何かあったときに対応しやすそうだと思ったのでRailsを選びました。
コードが複雑であり、Ruby自体を拡張するというRubyの機能をフル活用しているっぽい印象もあったのも選んだ理由ですね。

 

本題

ここから、実際に定義を見てみます。

今回見ていくメソッドは、ここにあります。

ターゲット:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/blank.rb

 

blank?メソッドは、Active Supportの中で定義されていました。
Railsでよく使われる便利メソッドの多くがここで定義されているようです。
Rubyで定義されているメソッドを拡張したり、あると便利な機能をオープンクラスを使って拡張したりと凶悪な側面もあります。

では、実際に中身を見てみます。

 

定義

[ruby]
def blank?
respond_to?(:empty?) ? !!empty? : !self
end
[/ruby]

定義はシンプルですね。
empty?メソッドが定義されていればそれを返し、そうでなければ自分自身の否定を返しています。
つまり、基本的にはempty?と似たような動きをしています。

「自分自身の否定」というのは、例えばRubyの場合は0もtrueとして扱うので「!0」はfalseとして返します。
Rubyのオブジェクトでfalse扱いになるのはfalseとnilだけであり、それ以外のオブジェクトはtrueとして扱われています。

挙動としては、メソッド名の通り「""」のような空文字や空配列など空白であるときにtrueを返します。
便利なところとしては、nilクラスにも定義されているので便利。

[ruby]
class NilClass
  def blank?
    true
  end
end
[/ruby]

NilClassと同様に、TrueClassやFalseClassにも定義されています。
また、ArrayやHashではempty?メソッドのaliasとしてblank?を定義しています。
つまり、どのクラスでも同じメソッドで呼べるようになっています。

注目すべきは、このblank?メソッドはObjectクラスで定義されているということですね。
Rubyで定義されているObjectクラスはすべてのクラスの親クラスなので、どのクラスでも使えるようになります。
便利ですね。

 

オープンクラス

どういうものか、ということは調べるとたくさん資料が出てきますが、簡単に言えば以下の通り。

オープンクラスとは、言語仕様として、クラスや継承やミックスインといった手続きなしに、既存のクラスを自在に拡張するようなコードを書けることを示します。

難しいが強力! Rubyのメタプログラミング、self、特異クラス/メソッド、オープンクラスとモンキーパッチ – @IT

ということで、ArrayやStringなどのRubyが提供しているクラス自体に独自に機能を追加することができるわけです。
頑張れば、メソッド定義などを動的に行うようなこともできてしまいます(いわゆる黒魔術)。
なお、Rubyの+や%など、ほかの言語では演算子と呼ばれるものもメソッドとして定義されているため、安易に上書きするとRuby自体を壊すこともできてしまいます。

Active Supportさんは、この強力であり怖さもあるオープンクラスを利用して、便利機能を追加しているわけです。

 

関連するメソッド

「blank?」に関連して、オブジェクトの存在確認に使われるメソッドとして「present?」があります。
このメソッドの定義も見てみましょう。

定義

[ruby]
def present?
  !blank?
end
[/ruby]

という感じで、blankでなければtrueを返します。
これもObjectクラスで定義されているために、すべてのクラスから利用することができるようになっています。

 

まとめ

さて、今回はRailsさんのコードを読んでみました。
本来であればactive_support.rbから読むべきなんでしょうが、処理が複雑だったり知らない書式が多いと先に進まないので簡単そうな部分から読んでみました。

メソッドの定義自体はシンプルなものであり、どこからでも同じように利用できるように工夫されていました。
こういうものを見ると、便利メソッドでも案外簡単な記述で書かれていることがわかりました。

また、Active Supportのコードを見てみると、実際の記述よりも説明に関するコメントが多いことがわかります。
どのような挙動をするのかを知ることができるので便利です。

今後も、不定期だとは思いますが適宜コードを読んでいこうと思います。
面白そうなものがあれば、またまとめます。

 

今回はここまで。
おわり

Posted by しきゆら