自分なりの PRagger - ActiveProperty
Yet Another Pragger -- BONNOH FRACTION 13
PRagger はソースコードが短かくて、中身がシンプルなので、しばらく使っていると自分なりの味を出したくなる気持ちは十分わかる。
ただ、起動時にプラグインをすべて読み込む(これが結構遅い)や Logger がないことや YAML はあまり好きじゃなかったなど理由はあった。
僕の場合、自分なりの改良を続けていった結果、別のものになっていってしまったけれども(プラグインも互換がないし)。
方針としては、データを収集したりする部分に特化し、加工部分は Ruby の文法で処理を記述でき、プラグインみたいな処理を追加したい場合は extend メソッドで追加していくような仕組みした。
これは今 Web ラジオの RSS 配信で使っている。
名前は思いつかなかったので、Active Record っぽいからということで、ActiveProperty にしている。
#!/usr/bin/ruby require 'open-uri' require 'kconv' module ActiveProperty class Base < Array @@instances = {} def self.site_url=(url) @@instances[self] = {} unless @@instances.key?(self) @@instances[self][:site_url] = url end def self.site_url if @@instances.key?(self) && @@instances[self].key?(:site_url) @@instances[self][:site_url] else nil end end def self.site_title=(title) @@instances[self] = {} unless @@instances.key?(self) @@instances[self][:site_title] = title end def self.site_title if @@instances.key?(self) && @@instances[self].key?(:site_title) @@instances[self][:site_title] else nil end end def self.prepare(&block) @@instances[self] = {} unless @@instances.key?(self) @@instances[self][:prepare] = block end def self.process(&block) @@instances[self] = {} unless @@instances.key?(self) @@instances[self][:process] = block end def self.split_block(options, &block) @@instances[self] = {} unless @@instances.key?(self) @@instances[self][:split_block_block] = block @@instances[self][:split_block_options] = options end def self.fetch return nil unless @@instances.key?(self) contents = '' begin open(@@instances[self][:site_url]) do |http| contents = http.read.toutf8 end rescue Exception => e # TODO: OpenURI::HTTPError, etc puts "#{@@instances[self][:site_url]} ... #{e.message}" end records = Extract.scan(contents, @@instances[self][:split_block_options], &@@instances[self][:split_block_block]) base = self.new records.each do |entry| r = entry r = @@instances[self][:after].call(entry) if @@instances[self].key?(:after) base << entry unless r.nil? end base end def self.after(&block) @@instances[self] = {} unless @@instances.key?(self) @@instances[self][:after] = block end end class Extract attr_accessor :records, :fields, :source def initialize(source) @source = source @records = [] @fields = {} end def self.scan(source, options, &block) extract = self.new(source) source.split(%r{#{options}}m).each do |data| extract.fields = {} extract.source = data extract.instance_eval(&block) extract.records << extract.fields unless extract.fields.empty? end extract.records end def record_limit(limit = 0) end def method_missing(name, *argv) # TODO: reg = argv[0] val = %r{#{reg}}m.match(@source).to_a[1] @fields[name] = val unless val.nil? end end end