マイペースなRailsおじさん

Ruby、Ruby on Rails、オブジェクト指向設計を主なテーマとして扱います。だんだん大きくなっていくRuby on Rails製プロダクトのメンテナンス性を損なわない方法を考えたり考えなかったりしている人のブログです。

RubyVM::AbstractSyntaxTreeを使ってソースコード内のデータを引っ張り出す

下記のようなソースコードdata.rbがあったとする

build([1, 3, 7, 0, 1, 3])

このソースコードでbuildに渡している引数の合計を、外部から取得して合計を求める。

code = File.read('data.rb')
root = RubyVM::AbstractSyntaxTree.parse(code, keep_script_lines: true)
args = nil
eval "args = #{root.children[2].children[1].source}"
args.sum # => 15

keep_script_lines: trueを指定するのがミソ。このオプションを指定してパースすると、ノードから#sourceを利用して元のソースコードを得ることができる。スゴイ。

まだ隠し機能らしく、ドキュメントの記載は薄い。 https://docs.ruby-lang.org/en/3.1/RubyVM/AbstractSyntaxTree.html