Upgrade to Pro — share decks privately, control downloads, hide ads and more …

†Ruby黒魔術経典†

 †Ruby黒魔術経典†

名古屋Ruby会議04 発表資料

Tomohiro Hashidate

June 08, 2019
Tweet

More Decks by Tomohiro Hashidate

Other Decks in Programming

Transcript

  1. We provide a web service as ... Analytics of Mobile

    Apps, Web Apps. Marketing Automation. We're hiring!!
  2. 守りの黒魔術 その4 TracePoint の利⽤は明⽰的に そして、絶対にensure でdisable すること。 途中で例外が発⽣するとtrace が有効のままになる。 trace

    が有効のままになるとマジで何が起きるか分からない。 フックが暴⾛してstack level too deep になるのはまだ良い⽅。
  3. 使えそうな機能の例 ( 続き) オブジェクト参照 _variable_get 系, const_get, ObjectSpace 変数/ 定数操作

    _variable_set 系, const_set メタデータ取得 Method やProc から取れる情報 メソッドの動的定義 define_method, module_eval
  4. proc の中で暗黙の内に it でパラメータを参照できるとは、 Ruby の動作に置き換えるとどういうことかを考えてみる。 評価コンテキスト内で it というローカル変数に値が⼊っている proc

    のself に it というメソッドが定義されていて、パラメータを取 得できる proc の外側で it が定義されている。 ローカル変数 or 引数 これらのどれかが実現できれば良さそう。
  5. 特定のメソッドを対象にPoC を書く module Ext def map(*args, &block) source = File.readlines(block.source_location[0])

    proc_binding = block.binding ast = RubyVM::AbstractSyntaxTree.of(block) args_tbl = ast.children[0] block_node = ast.children[2] if args_tbl.empty? extracted = extract_source( source, block_node.first_lineno, block_node.first_column, block_node.last_lineno, block_node.last_column) new_block = proc_binding.eval("proc { |it| #{extracted} }") super(*args, &new_block) else super(*args, &block) end end end Array.prepend(Ext) n = 3 [1, 2, 3].map { p it + n } # => [4, 5, 6]