Skip to content

Instantly share code, notes, and snippets.

@shinokaro
Created August 7, 2013 16:08
Show Gist options
  • Save shinokaro/6175501 to your computer and use it in GitHub Desktop.
Save shinokaro/6175501 to your computer and use it in GitHub Desktop.
class Script < Fiber
def self.new(*dsl_mods, &block)
Class.new(self).tap do |c|
# DSLメソッド郡をextendする、DSLを組み合わせ可能にしている
dsl_mods.each{ |mod| extend(mod) }
# 生成したクラスではnewメソッドでインスタンスを生成するように書き換える
c.class_eval do
def self.new(*args, &block)
self.allocate.__send__(:initialize, *args, &block)
end
end
# 生成したクラスのスコープでブロックを実行する。インスタンスメソッドのセットアップなどを想定
# 与えるブロック内でincludeを行えば良い
c.class_eval(&block) if block_given?
end
end
def initialize(*args, &block)
# スクリプトはFiberとして動作してほしいため、superでFiber化する
# resumeされた時に無名クラスを生成する、このとき自身を継承することによって
# スクリプト実行環境であるクラスメソッドとFiberインスタンスに干渉するための
# インスタンスメソッドを引き継がせる
# Fiberの特性上、resumeされるまでブロック内部は実行されないが、
# 引き数argsとblocKはこの時点で束縛される。
# argsを必要としたのはスクリプトファイルを読み込んで与える場合を想定したため。
# 無名モジュールに書き換えても良い。違いを利用するには追加コードが必要。
super(){
Class.new(self.class).class_eval(*args, &block)
}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment