instance_eval
instance_evalとは
フラットスコープよりもっと簡単にコードと束縛を好きなように組み合わせる方法がある。instance_eval
メソッドだ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
ブロックはレシーバをselfとしたコンテキストで評価されるので、ブロックからレシーバのプライベートメソッドや@vなどのインスタンス変数にアクセスできる。
instance_eval()に渡したブロックをコンテキスト探索機と呼ぶ。
カプセル化の破壊
このコンテキスト探索機を使うとカプセル化を破壊できてしまう。でもこのコンテキスト探索機が必要になる時がある。例えば、irbからオブジェクトの中身をすぐにみたいとかの場合もある。こういう場合、そのオブジェクトに入っていくにはinstance_eval
が最も近道になる。
テスト環境で何かのオブジェクトをテストする時も、データベースにアクセスするメソッドをシンプルな定数値と入れ替えることができる。
呼び出し可能オブジェクト
呼び出し可能オブジェクトに対しては前記事を書いたので、簡単にまとめてみる。
前の記事
ブロックの使用は2つに分けられる。まず、コードを保管する。それから、そのブロックを呼び出して実行する。でも、「コードを保管して、あとで呼び出す。」方式はブロックに限らない。Rubyではコードを保管できる場所が他に3つがある。
- Procの中。(ブロックがオブジェクトになったもの)
- lambdaの中。(Procの変形)
- メソッドの中。
Procオブジェクト
- ブロックはオブジェクトじゃない
- ブロックを保管して、あとで呼び出すためにはブロックがオブジェクトになる必要がある。そのために、Rubyの標準ライブラリProcがある
- ブロックを評価するには、Proc#call()で呼び出す
- ブロックを保管して、あとで呼び出す技術を遅延評価と呼ぶ
- ブロックをProcに変換する方法は4つがある
- Proc.new
- lambda()
- proc()
- &修飾
&Checkでのブロック
&Checkにはいくつかのところでブロックを使用している。まず、モデルクラスでのscope
にlambdaを多く使っている。
あと、SurveyGroup
モデルのvalidationに使っていて、そのコードは
1 2 3 4 5 6 |
|
ここはProcを使わずowner.is_a?(Conceptor)
だけ書くとエラーになるため、Procオブジェクトを使って値を渡している。
あとはVisualizeLogicService
で使っている。
1 2 3 4 5 6 |
|
上記のコードの中のprint_tree
はrubytree gem
からrequireされて使っていて、深くは知らないけど、そのメソッドの引数を渡すためにlambdaを使っている。