PraggerのconfigをRubyで書けるようにしてみた。
今更ながらPraggerを試してみた‥けどあまり萌えない - http://rubikitch.com/に移転しましたより、とりあえずはじめの一歩。
とりあえず、Array#call, Array#mapconcat!, Kernel#callを追加して、最初のeval_praggerを消しただけ。
#!/usr/bin/env ruby $KCODE='u' require 'yaml' require 'optparse' require 'kconv' require 'pathname' require 'base64' $plugins = {} class Plugin attr_reader :source def initialize(file) instance_eval( @source = File.read(file).toutf8, file , 1) end def self.load_plugins(folder = (Pathname.new(__FILE__).parent + "plugin")) Pathname.glob(folder + "**/*.rb").sort.each do |file| begin $plugins[ file.relative_path_from(folder).to_s.gsub("/","::")[0..-4] ]= Plugin.new(file) rescue LoadError end end end end class Array def call(module_name, config={}) STDERR.puts "exec plugin #{module_name}" replace $plugins[module_name].send(module_name.sub(/.*::/,""), config, self.dup) end def mapconcat! replace inject([]){|data,x| data.concat(yield(x))} end end def call(module_name, config={}) [].call(module_name, config) end def eval_pragger(command_array,data) command_array.inject(data) do |data, command| STDERR.puts "exec plugin #{command["module"]}" $plugins[command["module"]].send(command["module"].sub(/.*::/,""), command["config"] || {}, data.dup) end end Plugin.load_plugins()
おかげで以下のようなconfig.yamlを
- module: concat config: - module: RSS::load config: url: http://www.ruby-lang.org/ja/feeds/news.rss - module: concat config: - module: RSS::load config: url: http://www.ruby-lang.org/en/feeds/news.rss - module: stdout
より簡潔なconfig.rbで書くことができた。
#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'rb-pragger' a = %w[http://www.ruby-lang.org/ja/feeds/news.rss http://www.ruby-lang.org/en/feeds/news.rss] a.mapconcat! {|url| call("RSS::load", "url"=>url)} a.call("stdout")
moduleとconfigしか要素がないのに、いちいち書くのは冗長すぎるし、YAMLだとDRY原則に反しててやってられないんだが。
とりあえず今はquick hackなので、より洗練された記法は後程考えるとしよう。
ってはてなキーワードでPraggerをたどってみたら同じようなこと考えている人発見!こんな感じのDSLはいいんだけど、eval_praggerが使えないのが痛い。やっぱ俺は配列にメッセージを送る方が好きだな。処理を考えると自然だし。