From a8b3c2897576e87f8c7b0833b0c3610a8b4ae1a8 Mon Sep 17 00:00:00 2001 From: Michael Cetrulo Date: Wed, 16 May 2012 15:08:47 -0300 Subject: [PATCH] defining parser inheritance chain --- lib/planet/blog.rb | 4 ++- lib/planet/parsers.rb | 43 +++++++++++++++++++++++++------ lib/planet/parsers/base_parser.rb | 21 +++++++++++++++ 3 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 lib/planet/parsers/base_parser.rb diff --git a/lib/planet/blog.rb b/lib/planet/blog.rb index 02cdd5a..e907105 100644 --- a/lib/planet/blog.rb +++ b/lib/planet/blog.rb @@ -16,10 +16,12 @@ def initialize(attributes = {}) self.twitter = attributes[:twitter] self.posts = attributes.fetch(:posts, []) self.planet = attributes[:planet] + + @parsers = Parsers.new end def fetch - parser = self.type ? Parsers.get_parser(self.type) : Parsers.get_parser_for(self.feed) + parser = self.type ? @parsers.get_parser(self.type) : @parsers.get_parser_for(self.feed) feed = parser.fetch_and_parse(self.feed) diff --git a/lib/planet/parsers.rb b/lib/planet/parsers.rb index 00bf921..bb651ac 100644 --- a/lib/planet/parsers.rb +++ b/lib/planet/parsers.rb @@ -1,25 +1,52 @@ require 'feedzirra' +require 'set' class Planet class Parsers - @@parsers = [] + @@parsers = Set.new + + def self.add_parser(parser) + @@parsers << parser + end + + def initialize + @types, @domains = {}, {} - def self.get_parser(type) @@parsers.each do |parser| - return parser if parser.type == type + new_type, new_domains = parser.type, parser.domains + + fail("duplicate type") if new_type and @types.has_key? new_type + fail("overlapping domains") unless (@domains.keys & new_domains).empty? + + @types[new_type] = parser if new_type + new_domains.each do |new_domain| + @domains[new_domain] = parser + end end + end - raise ArgumentError, "no parser for type '#{ type }'", caller + def get_parser(type) + begin + return @types.fetch(type) + rescue KeyError => e + raise(ArgumentError, "No parser for type '#{ type }'", caller) + end end - def self.get_parser_for(feed) + def get_parser_for(feed) feed_domain = URI(feed).host - @@parsers.each do |parser| - return parser if parser.domains.any? { |domain| feed_domain.end_with? domain } + @domains.each do |domain, parser| + return parser if feed_domain.end_with? domain end - return Feedzirra::Feed + return Feedzirra::Feed # default generic parser end end end + +# load parsers +dirname = File.join([File.dirname(__FILE__), 'parsers']) +Dir.open(dirname).each do |filename| + require "#{dirname}/#{filename}" if filename.end_with? '.rb' +end diff --git a/lib/planet/parsers/base_parser.rb b/lib/planet/parsers/base_parser.rb new file mode 100644 index 0000000..6b4f737 --- /dev/null +++ b/lib/planet/parsers/base_parser.rb @@ -0,0 +1,21 @@ +class Planet + class Parsers + class BaseParser + def self.type + @type + end + + def self.domains + @domains || [] + end + + def self.inherited(parser) + Parsers.add_parser parser + end + + def self.fetch_and_parse(feed) + raise(Exception, "Not implemented", caller) + end + end + end +end