Forum: Ruby program design - template design pattern

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Adam A. (Guest)
on 2009-03-26 08:25
although im making a rails app this is more specific to ruby and general
coding.


I want to access several preknown rss feeds, parse and extract the
relevant data and store it into an array. The feeds all have similiar
content but the structure differs. That means my extracting regexps etc
will differ for each feed.

I want to do something like this

items = []
feeds.each do |feed|
   clean_up(feed) #squeeze and strip stuff etc
   item = parse(feed)
   items << item
end
return items

where the code in parse() will vary depedning on the feed.

i know of the template design patter and can implement it but how will i
select the correct parse method for a given feed?

will i have to have a case control structure in the block which will
determine which feed is currently being processed and then apply the
correct parse method? If i had 50 feeds that could be one huge case
structure.. is there a more elegant way?

any tips would be greatly appreciated.
Srijayanth S. (Guest)
on 2009-03-26 12:29
(Received via mailing list)
While a lot depends on several other aspects of your project, this
specific
problem depends on a principle question:

Do you have any control over the feed object?

If you have any control, then you could make a polymorphic superclass
called
Feed and go on from there where each separate feed has its own related
methods to deal with its idiosyncrasies and polymorphic methods that
deal
with common tasks. For ex:

class Feed
   def initialize
   end
   def parse_content
   end
end

class BbcFeed < Feed
   def parse_content
      # do something relevant here
      # probably return a string/hash/or content object
   end
   # define other methods specific to BbcFeed etc
end

Once this is done, you just have to create the right object at runtime,
perhaps have a factory object detailing this.

If you don't have control, there isn't a way to run away from doing
checks
on the object. Depending on how you determine the regex to use, you
could
have specific solutions. Perhaps each feed has a different URL that you
could use to determine the parsing, or perhaps something else in the
xml...either way, you have to know what object you are dealing with, or
you
have to write a parser that deals with it.

From your pseudo code, it would seem that you are still not thinking in
terms of object oriented code. For ex:

clean_up(feed)
parse(feed)

If you have to do it using OO, you probably want to assign those
behaviors
to specific objects. But don't listen to me, I am not very good at this.

Hope this helps.

Jayanth
Robert K. (Guest)
on 2009-03-26 12:57
(Received via mailing list)
2009/3/26 Srijayanth S. <removed_email_address@domain.invalid>:
> While a lot depends on several other aspects of your project, this specific
> problem depends on a principle question:
>
> Do you have any control over the feed object?

I second that.  Also, what type is "feed"?  That's not clear to me.

> If you have any control, then you could make a polymorphic superclass called
> Feed and go on from there where each separate feed has its own related
> methods to deal with its idiosyncrasies and polymorphic methods that deal
> with common tasks. For ex:
>
> class Feed
>   def initialize
>   end
>   def parse_content
>   end

One could also add

  # download the feed
  def fetch(uri)
     ....
  end

> Once this is done, you just have to create the right object at runtime,
> perhaps have a factory object detailing this.

Or stuff the relationship between feed URI's and class that deals with
it in a Hash:

FEEDS = {
  'http://foo.bar/feed.rdf' => BbcFeed,
  'http://baz.boz.buz/path.rdf' => BbcFeed,
  'http://what.ever.you/like' => OtherFeed,
}.freeze

Then you can do

FEEDS.each |uri, cl|
  feed_handler = cl.new
  feed_handler.fetch
  feed_handler.parse_content
end

> If you don't have control, there isn't a way to run away from doing checks
> on the object. Depending on how you determine the regex to use, you could
> have specific solutions. Perhaps each feed has a different URL that you
> could use to determine the parsing, or perhaps something else in the
> xml...either way, you have to know what object you are dealing with, or you
> have to write a parser that deals with it.

Feed type checks could be done on the URI or the content.  Depending
on that a different approach needs to be followed but the basic
pattern stays the same.

Kind regards

robert
Srijayanth S. (Guest)
on 2009-03-26 13:31
(Received via mailing list)
On Thu, Mar 26, 2009 at 4:23 PM, Robert K.
<removed_email_address@domain.invalid>wrote:

> called
> One could also add
> >      # do something relevant here
>
>  feed_handler.fetch
> > have to write a parser that deals with it.
>
> Feed type checks could be done on the URI or the content.  Depending
> on that a different approach needs to be followed but the basic
> pattern stays the same.


Yeah I thought of that too, but God knows what his criterion for
choosing
the parser are. It might be more complex than just a simple uri mapping.


Jayanth
Adam A. (Guest)
on 2009-03-27 02:35
Hi all,

thanks for you comments. Yes Im referring to rss feeds and i am in full
controll of how they are represented. Im choosing the feed addresses,
fetching them and parsing them.

I actually got confused between my patterns, it was the strategy pattern
not the template pattern. But at the end of the day it all boiled down
to how I could dynamically initialize each feed_parser and thats where i
got stuck mainly due to lack of programming experience.

I didnt know I could store class names in hashes but after reading up on
Ruby Desing Patterns i found out they are objects themselves.

So Ill think ill use the hash idea!

Thank you all so much for your suggestions.
Robert K. (Guest)
on 2009-03-27 09:58
(Received via mailing list)
2009/3/27 Adam A. <removed_email_address@domain.invalid>:

> I actually got confused between my patterns, it was the strategy pattern
> not the template pattern. But at the end of the day it all boiled down
> to how I could dynamically initialize each feed_parser and thats where i
> got stuck mainly due to lack of programming experience.
>
> I didnt know I could store class names in hashes but after reading up on

Actually those were not class names but class _objects_ themselves in
my example!

> Ruby Desing Patterns i found out they are objects themselves.
>
> So Ill think ill use the hash idea!

So I conclude from that that you know which feed needs which parsing
algorithm.

> Thank you all so much for your suggestions.

You're welcome!

Kind regards

robert
This topic is locked and can not be replied to.