LoginSignup
3
1

More than 3 years have passed since last update.

method_sourceってgemを読んだら知恵が詰まってた。

Posted at

method_source is 何?

minimum sample

require 'method_source'

def my_important_method
  # do nothing, just sleep
  sleep 4 
  'successfuly done with my hard work!!'
end

method = method(:my_important_method)
method.source.display

すると。。。

def my_important_method
  # do nothing, just sleep
  sleep 4 
  'successfuly done with my hard work!!'
end

メソッドの定義がプリントされる。

どんな実装か

Method objectからは定義もとのfile, lineが取れる。
そのファイルを全部読み込み、line以下を全て取ってくる

lines = File.readlines(file)
lines = lines[(line - 1)..-1]

linesをイテレートして、methodの定義が終わるところを判定する。

lines.each do |v|
  code << v
  return code if complete_expression?(block ? block.call(code) : code)
end

これでmethod定義が抜き出せたので、あとは表示するだけ

知恵

rescueされるerrorを判別するだけのmodule

def hoge
  rescue MyModule
end

module MyModule
  def self.===(error)
    some_condition(error)
  end
end

evalを使ってstrの構文をチェックだけして、BEGIN throwで実行させずに戻る

catch(:valid) do
  eval("BEGIN{throw :valid}\n#{str}")
end

どうゆう仕組みか?
strが構文としておかしいとSyntaxErrorが出て throwされない。
strが構文としてokだったらそのstr実行前に BEGIN で登録された throwが走る。

所感

まず BEGIN とか知らなかった。
この3行でこれだけのこと詰め込めるrubyはスマートで好き。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1