jsl-myzofeedtosis 0.0.1.2 → 0.0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -1,108 +1,140 @@
1
1
  = Description
2
2
 
3
- Myzofeedtosis is a library that helps you to efficiently process syndicated web resources. It helps by automatically using
4
- conditional HTTP GET requests, as well as by pointing out which entries are new in any given feed.
3
+ Myzofeedtosis is a library that helps you to efficiently process syndicated web
4
+ resources. It helps by automatically using conditional HTTP GET requests, as
5
+ well as by pointing out which entries are new in any given feed.
5
6
 
6
7
  == Name
7
8
 
8
- The name "myzofeedtosis" is based on the form of cellular digestion "myzocytosis". According to Wikipedia [1], myzocytosis
9
- is described as the process where "one cell pierces another using a feeding tube, and sucks out cytoplasm". Myzofeedtosis is
10
- kind of like that, except it works with RSS/Atom feeds instead of cytoplasm.
9
+ The name "myzofeedtosis" is based on the form of cellular digestion
10
+ "myzocytosis". According to Wikipedia [1], myzocytosis is described as the
11
+ process where "one cell pierces another using a feeding tube, and sucks out
12
+ cytoplasm". Myzofeedtosis is kind of like that, except it works with RSS/Atom
13
+ feeds instead of cytoplasm.
11
14
 
12
15
  1 - http://en.wikipedia.org/wiki/List_of_vores
13
16
 
14
17
  == Philosophy
15
18
 
16
- Myzofeedtosis is designed to help you with book-keeping about feed fetching details. This is usually something that is
17
- mundane and not fundamentally related to the business logic of applications that deal with the consumption of syndicated
18
- content on the web. Myzofeedtosis keeps track of these mundane details so you can just keep grabbing new content without
19
- wasting bandwidth in making unnecessary requests and programmer time in implementing algorithms to figure out which feed
20
- entries are new.
21
-
22
- Myzofeedtosis fits into other frameworks to do the heavy lifting, including the Curb library which does HTTP requests through
23
- curl, and FeedNormalizer which abstracts the differences between syndication formats. In the sense that it fits into these
24
- existing, robust programs, Myzofeedtosis is a modular middleware piece that efficiently glues together disparate parts to create
25
- a helpful feed reader with a minimal (< 200 LOC), test-covered codebase.
19
+ Myzofeedtosis is designed to help you with book-keeping about feed fetching
20
+ details. This is usually something that is mundane and not fundamentally related
21
+ to the business logic of applications that deal with the consumption of
22
+ syndicated content on the web. Myzofeedtosis keeps track of these mundane
23
+ details so you can just keep grabbing new content without wasting bandwidth in
24
+ making unnecessary requests and programmer time in implementing algorithms to
25
+ figure out which feed entries are new.
26
+
27
+ Myzofeedtosis fits into other frameworks to do the heavy lifting, including the
28
+ Curb library which does HTTP requests through curl, and FeedNormalizer which
29
+ abstracts the differences between syndication formats. In the sense that it fits
30
+ into these existing, robust programs, Myzofeedtosis is a modular middleware
31
+ piece that efficiently glues together disparate parts to create a helpful feed
32
+ reader with a minimal (< 200 LOC), test-covered codebase.
26
33
 
27
34
  == Installation
28
35
 
29
- Assuming that you've followed the directions on gems.github.com to allow your computer to install gems from GitHub, the
30
- following command will install the Myzofeedtosis library:
36
+ Assuming that you've followed the directions on gems.github.com to allow your
37
+ computer to install gems from GitHub, the following command will install the
38
+ Myzofeedtosis library:
31
39
 
32
- sudo gem install jsl-myzofeedtosis
40
+ sudo gem install jsl-myzofeedtosis
33
41
 
34
42
  == Usage
35
43
 
36
- Myzofeedtosis is easy to use. Just create a client object, and invoke the "fetch" method:
37
-
38
- require 'myzofeedtosis'
39
- client = Myzofeedtosis::Client.new('http://feeds.feedburner.com/wooster')
40
- result = client.fetch
41
-
42
- +result+ will be a FeedNormalizer::Feed object, which responds to the method +entries+. In this first case, Myzofeedtosis
43
- isn't much more useful than just using FeedNormalizer by itself. On subsequent requests, though, it helps significantly.
44
- Invoke client.fetch again. Instead of getting back an object that responds to +entries+, you'll probably get back a Curl::Easy
45
- object with a response code of 304, indicating that the resource hasn't changed since the last retrieval. If you invoke
46
- fetch again, assuming one entry was added, you would get back another FeedNormalizer::Feed object. You'll also notice that
47
- all of the FeedNormalizer::Feed objects respond not only to +entries+, but +new_entries+, which is a selection of the entries
48
- that haven't been seen before.
49
-
50
- Myzofeedtosis is designed for these situations where you have one or maybe thousands of feeds that you have to update on a
51
- regular basis. If the results that you receive respond to the method new_entries, iterate over the new entries, processing them
52
- according to your business logic.
53
-
54
- You will most likely want to allow Myzofeedtosis to remember details about the last retrieval of a feed after the client is
55
- removed from memory. Myzofeedtosis uses Moneta, a unified interface to key-value storage systems to remember "summaries" of
56
- feeds that it has seen in the past. See the document section on Customization for more details on how to configure this system.
44
+ Myzofeedtosis is easy to use. Just create a client object, and invoke the
45
+ "fetch" method:
46
+
47
+ require 'myzofeedtosis'
48
+ client = Myzofeedtosis::Client.new('http://feeds.feedburner.com/wooster')
49
+ result = client.fetch
50
+
51
+ +result+ will be a Myzofeedtosis::Result object which delegates methods to
52
+ the FeedNormalizer::Feed object as well as the Curl::Easy object used to fetch
53
+ the feed. Useful methods on this object include +entries+, +new_entries+ and
54
+ +response_code+ among many others (basically all of the methods that
55
+ FeedNormalizer::Feed and Curl::Easy objects respond to should be implemented).
56
+
57
+ Note that since Myzofeedtosis uses HTTP conditional GET, it may not actually
58
+ have received a full XML response from the server suitable for being parsed
59
+ into entries. In this case, methods such as +entries+ on the Myzofeedtosis::Result
60
+ will return +nil+. Depending on your application logic, you may want to inspect
61
+ the methods that are delegated to the Curl::Easy object, such as +response_code+,
62
+ for more information on what happened in these cases.
63
+
64
+ On subsequent requests of a particular resource, Myzofeedtosis will update
65
+ +new_entries+ to contain the feed entries that we haven't seen yet. In most
66
+ applications, your program will probably call the same batch of URLS multiple
67
+ times, and process the elements in +new_entries+.
68
+
69
+ You will most likely want to allow Myzofeedtosis to remember details about the
70
+ last retrieval of a feed after the client is removed from memory. Myzofeedtosis
71
+ uses Moneta, a unified interface to key-value storage systems to remember
72
+ "summaries" of feeds that it has seen in the past. See the document section on
73
+ Customization for more details on how to configure this system.
57
74
 
58
75
  == Customization
59
76
 
60
- Myzofeedtosis stores summaries of feeds in a key-value storage system. If no options are included when creating a new
61
- Myzofeedtosis::Client object, the default is to use a "memory" storage system. The memory system is just a basic ruby Hash, so it
62
- won't keep track of feeds after a particular Client is removed from memory. To configure a different backend, pass an options hash
63
- to the Myzofeedtosis client initialization:
77
+ Myzofeedtosis stores summaries of feeds in a key-value storage system. If no
78
+ options are included when creating a new Myzofeedtosis::Client object, the
79
+ default is to use a "memory" storage system. The memory system is just a basic
80
+ ruby Hash, so it won't keep track of feeds after a particular Client is removed
81
+ from memory. To configure a different backend, pass an options hash to the
82
+ Myzofeedtosis client initialization:
64
83
 
65
- url = "http://newsrss.bbc.co.uk/rss/newsonline_world_edition/south_asia/rss.xml"
66
- mf = Myzofeedtosis::Client.new(url, :backend => {:moneta_klass => 'Moneta::Memcache', :server => 'localhost:1978'})
67
- res = mf.fetch
68
-
69
- This example sets up a Memcache backend, which in this case points to Tokyo Tyrant on port 1978. Note that Moneta::Memcache
70
- can be given as a string, in which case you don't have to manually require Moneta::Memcache before initializing the client.
84
+ url = "http://newsrss.bbc.co.uk/rss/newsonline_world_edition/south_asia/rss.xml"
85
+ mf = Myzofeedtosis::Client.new(url, :backend => {:moneta_klass => 'Moneta::Memcache', :server => 'localhost:1978'})
86
+ res = mf.fetch
71
87
 
72
- Generally, Myzofeedtosis supports all systems supported by Moneta, and any one of the supported systems can be given to the
73
- +moneta_klass+ parameter. Other options following +backend+ are passed directly to Moneta for configuration.
88
+ This example sets up a Memcache backend, which in this case points to Tokyo
89
+ Tyrant on port 1978. Note that Moneta::Memcache can be given as a string, in
90
+ which case you don't have to manually require Moneta::Memcache before
91
+ initializing the client.
74
92
 
75
- == Implementation
93
+ Generally, Myzofeedtosis supports all systems supported by Moneta, and any one
94
+ of the supported systems can be given to the +moneta_klass+ parameter. Other
95
+ options following +backend+ are passed directly to Moneta for configuration.
76
96
 
77
- Myzofeedtosis helps to identify new feed entries and to figure out when conditional GET can be used in retrieving resources. In
78
- order to accomplish this without having to require that the user store information such as etags and dates of the last retrieved entry,
79
- Myzofeedtosis stores a summary structure in the configured key-value store (backed by Moneta). In order to do conditional GET
80
- requests, Myzofeedtosis stores the Last-Modified date, as well as the ETag of the last request in the summary structure, which is
81
- put in a namespaced element consisting of the term 'Myzofeedtosis' (bet you won't have to worry about name collisions on that one!)
82
- and the MD5 of the URL retrieved.
97
+ == Implementation
83
98
 
84
- It can also be a bit tricky to decipher which feed entries are new since many feed sources don't include unique ids with their
85
- feeds. Myzofeedtosis reliably keeps track of which entries in a feed are new by storing (in the summary hash mentioned above) an
86
- MD5 signature of each entry in a feed. It takes elements such as the published-at date, title and content and generates the MD5
87
- of these elements. This allows Myzofeedtosis to cheaply compute (both in terms of computation and storage) which feed entries
88
- should be presented to the user as "new". Below is an example of a summary structure:
99
+ Myzofeedtosis helps to identify new feed entries and to figure out when
100
+ conditional GET can be used in retrieving resources. In order to accomplish this
101
+ without having to require that the user store information such as etags and
102
+ dates of the last retrieved entry, Myzofeedtosis stores a summary structure in
103
+ the configured key-value store (backed by Moneta). In order to do conditional
104
+ GET requests, Myzofeedtosis stores the Last-Modified date, as well as the ETag
105
+ of the last request in the summary structure, which is put in a namespaced
106
+ element consisting of the term 'Myzofeedtosis' (bet you won't have to worry
107
+ about name collisions on that one!) and the MD5 of the URL retrieved.
108
+
109
+ It can also be a bit tricky to decipher which feed entries are new since many
110
+ feed sources don't include unique ids with their feeds. Myzofeedtosis reliably
111
+ keeps track of which entries in a feed are new by storing (in the summary hash
112
+ mentioned above) an MD5 signature of each entry in a feed. It takes elements
113
+ such as the published-at date, title and content and generates the MD5 of these
114
+ elements. This allows Myzofeedtosis to cheaply compute (both in terms of
115
+ computation and storage) which feed entries should be presented to the user as
116
+ "new". Below is an example of a summary structure:
89
117
 
90
118
  {
91
- :etag=>"4c8f-46ac09fbbe940", :last_modified=>"Mon, 25 May 2009 18:17:33 GMT",
92
- :digests=>["f2993783ded928637ce5f2dc2d837f10", "da64efa6dd9ce34e5699b9efe73a37a7"]
119
+ :etag => "4c8f-46ac09fbbe940",
120
+ :last_modified => "Mon, 25 May 2009 18:17:33 GMT",
121
+ :digests => ["f2993783ded928637ce5f2dc2d837f10", "da64efa6dd9ce34e5699b9efe73a37a7"]
93
122
  }
94
-
95
- The data stored by Myzofeedtosis in the summary structure allows it to be helpful to the user without storing lots of
96
- data that are unnecessary for efficient functioning.
123
+
124
+ The data stored by Myzofeedtosis in the summary structure allows it to be
125
+ helpful to the user without storing lots of data that are unnecessary for
126
+ efficient functioning.
97
127
 
98
128
  == HTML cleaning/sanitizing
99
129
 
100
- Myzofeedtosis doesn't do anything about feed sanitizing, as other libraries have been built for this purpose. FeedNormalizer
101
- has methods for escaping entries, but to strip HTML I suggest that you look at the Ruby gem "sanitize".
130
+ Myzofeedtosis doesn't do anything about feed sanitizing, as other libraries have
131
+ been built for this purpose. FeedNormalizer has methods for escaping entries,
132
+ but to strip HTML I suggest that you look at the Ruby gem "sanitize".
102
133
 
103
134
  == Feedback
104
135
 
105
- Please let me know if you have any problems with or questions about Myzofeedtosis.
136
+ Please let me know if you have any problems with or questions about
137
+ Myzofeedtosis.
106
138
 
107
139
  = Author
108
140
 
data/lib/myzofeedtosis.rb CHANGED
@@ -10,5 +10,7 @@ lib_dirs = [ 'extensions', 'myzofeedtosis' ].map do |d|
10
10
  end
11
11
 
12
12
  lib_dirs.each do |d|
13
- Dir[File.join(d, "**", "*.rb")].each {|file| require file }
13
+ Dir[File.join(d, "**", "*.rb")].each do |file|
14
+ require file
15
+ end
14
16
  end
@@ -1,9 +1,11 @@
1
1
  module Myzofeedtosis
2
2
 
3
- # Myzofeedtosis::Client is the primary interface to the feed reader. Call it with a url that was previously fetched while
4
- # connected to the configured backend, and it will 1) only do a retrieval if deemed necessary based on the etag and modified-at
5
- # of the last etag and 2) mark all entries retrieved as either new or not new. Entries retrieved are normalized using
6
- # the feed-normalizer gem.
3
+ # Myzofeedtosis::Client is the primary interface to the feed reader. Call it
4
+ # with a url that was previously fetched while connected to the configured
5
+ # backend, and it will 1) only do a retrieval if deemed necessary based on the
6
+ # etag and modified-at of the last etag and 2) mark all entries retrieved as
7
+ # either new or not new. Entries retrieved are normalized using the
8
+ # feed-normalizer gem.
7
9
  class Client
8
10
  attr_reader :options, :url
9
11
 
@@ -22,22 +24,25 @@ module Myzofeedtosis
22
24
  @options[:backend].except(:moneta_klass) )
23
25
  end
24
26
 
25
- # Retrieves the latest entries from this feed. Returns a Feednormalizer::Feed object with
26
- # method +new_entries+ if the response was successful, otherwise returns the Curl::Easy object
27
- # that we used to retrieve this resource. Note that we also return this object if the request
28
- # resulted in a 304 (Not Modified) response code since we don't have any new results. Depending
29
- # on your business logic, you may want to do something in this case, such as putting this
30
- # resource in a lower-priority queue if it is not frequently updated.
27
+ # Retrieves the latest entries from this feed. Returns a
28
+ # Feednormalizer::Feed object with method +new_entries+ if the response was
29
+ # successful, otherwise returns the Curl::Easy object that we used to
30
+ # retrieve this resource. Note that we also return this object if the
31
+ # request resulted in a 304 (Not Modified) response code since we don't have
32
+ # any new results. Depending on your business logic, you may want to do
33
+ # something in this case, such as putting this resource in a lower-priority
34
+ # queue if it is not frequently updated.
31
35
  def fetch
32
36
  curl = build_curl_easy
33
37
  curl.perform
34
- process_curl_response(curl)
38
+ feed = process_curl_response(curl)
39
+ Myzofeedtosis::Result.new(curl, feed)
35
40
  end
36
41
 
37
42
  private
38
43
 
39
- # Marks entries as either seen or not seen based on the unique signature of the entry, which
40
- # is calculated by taking the MD5 of common attributes.
44
+ # Marks entries as either seen or not seen based on the unique signature of
45
+ # the entry, which is calculated by taking the MD5 of common attributes.
41
46
  def mark_new_entries(response)
42
47
  digests = if summary_for_feed.nil? || summary_for_feed[:digests].nil?
43
48
  [ ]
@@ -45,8 +50,8 @@ module Myzofeedtosis
45
50
  summary_for_feed[:digests]
46
51
  end
47
52
 
48
- # For each entry in the responses object, mark @_seen as false if the digest of this entry
49
- # doesn't exist in the cached object.
53
+ # For each entry in the responses object, mark @_seen as false if the
54
+ # digest of this entry doesn't exist in the cached object.
50
55
  response.entries.each do |e|
51
56
  seen = digests.include?(digest_for(e))
52
57
  e.instance_variable_set(:@_seen, seen)
@@ -63,17 +68,16 @@ module Myzofeedtosis
63
68
  response = mark_new_entries(response)
64
69
  store_summary_to_backend(response, curl)
65
70
  response
66
- else
67
- curl
68
71
  end
69
72
  end
70
73
 
71
- # Sets options for the Curl::Easy object, including parameters for HTTP conditional GET.
74
+ # Sets options for the Curl::Easy object, including parameters for HTTP
75
+ # conditional GET.
72
76
  def build_curl_easy
73
77
  curl = new_curl_easy(url)
74
78
 
75
- # Many feeds have a 302 redirect to another URL. For more recent versions of Curl,
76
- # we need to specify this.
79
+ # Many feeds have a 302 redirect to another URL. For more recent versions
80
+ # of Curl, we need to specify this.
77
81
  curl.follow_location = true
78
82
 
79
83
  set_header_options(curl)
@@ -93,8 +97,8 @@ module Myzofeedtosis
93
97
  summary = summary_for_feed
94
98
 
95
99
  unless summary.nil?
96
- # We should only try to populate the headers for a conditional GET if we know both
97
- # of these values.
100
+ # We should only try to populate the headers for a conditional GET if
101
+ # we know both of these values.
98
102
  if summary[:etag] && summary[:last_modified]
99
103
  curl.headers['If-None-Match'] = summary[:etag]
100
104
  curl.headers['If-Modified-Since'] = summary[:last_modified]
@@ -108,9 +112,10 @@ module Myzofeedtosis
108
112
  MD5.hexdigest(@url)
109
113
  end
110
114
 
111
- # Stores information about the retrieval, including ETag, Last-Modified, and MD5 digests of all
112
- # entries to the backend store. This enables conditional GET usage on subsequent requests and
113
- # marking of entries as either new or seen.
115
+ # Stores information about the retrieval, including ETag, Last-Modified,
116
+ # and MD5 digests of all entries to the backend store. This enables
117
+ # conditional GET usage on subsequent requests and marking of entries as
118
+ # either new or seen.
114
119
  def store_summary_to_backend(feed, curl)
115
120
  headers = HttpHeaders.new(curl.header_str)
116
121
 
@@ -120,7 +125,8 @@ module Myzofeedtosis
120
125
  summary.merge!(:etag => headers.etag) unless headers.etag.nil?
121
126
  summary.merge!(:last_modified => headers.last_modified) unless headers.last_modified.nil?
122
127
 
123
- # Store digest for each feed entry so we can detect new feeds on the next retrieval
128
+ # Store digest for each feed entry so we can detect new feeds on the next
129
+ # retrieval
124
130
  digests = feed.entries.map do |e|
125
131
  digest_for(e)
126
132
  end
@@ -133,11 +139,12 @@ module Myzofeedtosis
133
139
  @backend[key_for_cached] = summary
134
140
  end
135
141
 
136
- # Computes a unique signature for the FeedNormalizer::Entry object given. This signature
137
- # will be the MD5 of enough fields to have a reasonable probability of determining if the
138
- # entry is unique or not.
142
+ # Computes a unique signature for the FeedNormalizer::Entry object given.
143
+ # This signature will be the MD5 of enough fields to have a reasonable
144
+ # probability of determining if the entry is unique or not.
139
145
  def digest_for(entry)
140
- MD5.hexdigest([entry.date_published, entry.url, entry.title, entry.content].join)
146
+ MD5.hexdigest( [ entry.date_published, entry.url, entry.title,
147
+ entry.content ].join)
141
148
  end
142
149
 
143
150
  def parser_for_xml(xml)
@@ -0,0 +1,43 @@
1
+ module Myzofeedtosis
2
+
3
+ # Makes the response components both from the Curl::Easy object and the
4
+ # FeedNormalizer::Feed object available to the user by delegating appropriate
5
+ # method calls to the correct object. If FeedNormalizer wasn't able to process
6
+ # the response, calls which would be delegated to this object return nil. In
7
+ # these cases, depending on your business logic you may want to inspect the
8
+ # state of the Curl::Easy object.
9
+ class Result
10
+
11
+ # Methods which should be delegated to the FeedNormalizer::Feed object.
12
+ FEED_METHODS = [ :title, :description, :last_updated, :copyright, :authors,
13
+ :author, :urls, :url, :image, :generator, :items, :entries, :new_items,
14
+ :new_entries, :channel, :ttl, :skip_hours, :skip_days
15
+ ] unless defined?(FEED_METHODS)
16
+
17
+ def initialize(curl, feed)
18
+ @curl = curl
19
+ @feed = feed
20
+
21
+ raise ArgumentError, "Curl object must not be nil" if curl.nil?
22
+
23
+ # See what the Curl::Easy object responds to, and send any appropriate
24
+ # messages its way.
25
+ @curl.public_methods(false).each do |meth|
26
+ (class << self; self; end).class_eval do
27
+ define_method meth do |*args|
28
+ @curl.send(meth, *args)
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ # Send methods through to the feed object unless it is nil. If feed
35
+ # object is nil, return nil in response to method call.
36
+ FEED_METHODS.each do |meth|
37
+ define_method meth do |*args|
38
+ @feed.nil? ? nil : @feed.__send__(meth, *args)
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{myzofeedtosis}
3
- s.version = "0.0.1.2"
3
+ s.version = "0.0.1.4"
4
4
 
5
5
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
6
  s.authors = ["Justin Leitgeb"]
@@ -9,10 +9,16 @@ Gem::Specification.new do |s|
9
9
  s.email = %q{justin@phq.org}
10
10
 
11
11
  s.files = ["lib/extensions/core/array.rb", "lib/extensions/core/hash.rb",
12
- "lib/extensions/feed_normalizer/feed_instance_methods.rb", "lib/myzofeedtosis/client.rb", "lib/myzofeedtosis.rb",
13
- "LICENSE", "myzofeedtosis.gemspec", "Rakefile", "README.rdoc", "spec/extensions/feed_normalizer/feed_instance_methods_spec.rb",
14
- "spec/fixtures/http_headers/wooster.txt", "spec/fixtures/xml/older_wooster.xml", "spec/fixtures/xml/wooster.xml",
15
- "spec/myzofeedtosis/client_spec.rb", "spec/myzofeedtosis_spec.rb", "spec/spec_helper.rb"]
12
+ "lib/extensions/feed_normalizer/feed_instance_methods.rb",
13
+ "lib/myzofeedtosis/result.rb",
14
+ "lib/myzofeedtosis/client.rb", "lib/myzofeedtosis.rb", "LICENSE",
15
+ "myzofeedtosis.gemspec", "Rakefile", "README.rdoc",
16
+ "spec/extensions/feed_normalizer/feed_instance_methods_spec.rb",
17
+ "spec/fixtures/http_headers/wooster.txt",
18
+ "spec/fixtures/xml/older_wooster.xml", "spec/fixtures/xml/wooster.xml",
19
+ "spec/myzofeedtosis/client_spec.rb", "spec/myzofeedtosis_spec.rb",
20
+ "spec/myzofeedtosis/result_spec.rb",
21
+ "spec/spec_helper.rb"]
16
22
 
17
23
  s.has_rdoc = true
18
24
  s.homepage = %q{http://github.com/jsl/myzofeedtosis}
@@ -20,7 +26,8 @@ Gem::Specification.new do |s|
20
26
  s.require_paths = ["lib"]
21
27
  s.rubygems_version = %q{1.3.1}
22
28
  s.summary = %q{Retrieves feeds using conditional GET and marks entries that you haven't seen before}
23
- s.test_files = ["spec/myzofeedtosis_spec.rb", "spec/spec_helper.rb", "spec/myzofeedtosis/client_spec.rb"]
29
+ s.test_files = ["spec/myzofeedtosis_spec.rb", "spec/spec_helper.rb", "spec/myzofeedtosis/client_spec.rb",
30
+ "spec/myzofeedtosis/result_spec.rb" ]
24
31
 
25
32
  s.extra_rdoc_files = [ "README.rdoc" ]
26
33
 
@@ -2,9 +2,9 @@ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
2
 
3
3
  describe Myzofeedtosis::Client do
4
4
  before do
5
- @url = "http://www.example.com/feed.rss"
5
+ @url = "http://www.example.com/feed.rss"
6
6
  @opts = { :user_agent => "My Cool Application" }
7
- @fr = Myzofeedtosis::Client.new(@url, @opts)
7
+ @fr = Myzofeedtosis::Client.new(@url, @opts)
8
8
  end
9
9
 
10
10
  describe "initialization" do
@@ -46,10 +46,18 @@ describe Myzofeedtosis::Client do
46
46
  end
47
47
 
48
48
  describe "when the response code is not 200" do
49
- it "should return the Curl::Easy object" do
49
+ it "should return nil for feed methods such as #title and #author" do
50
50
  curl = mock('curl', :perform => true, :response_code => 304)
51
51
  @fr.expects(:build_curl_easy).returns(curl)
52
- @fr.fetch.should == curl
52
+ res = @fr.fetch
53
+ res.title.should be_nil
54
+ res.author.should be_nil
55
+ end
56
+
57
+ it "should return a Myzofeedtosis::Result object" do
58
+ curl = mock('curl', :perform => true, :response_code => 304)
59
+ @fr.expects(:build_curl_easy).returns(curl)
60
+ @fr.fetch.should be_a(Myzofeedtosis::Result)
53
61
  end
54
62
  end
55
63
 
@@ -59,7 +67,7 @@ describe Myzofeedtosis::Client do
59
67
  curl = mock('curl', :perform => true, :response_code => 200,
60
68
  :body_str => xml_fixture('wooster'), :header_str => http_header('wooster'))
61
69
  @fr.expects(:build_curl_easy).returns(curl)
62
- @fr.fetch
70
+ @fr.fetch
63
71
  end
64
72
 
65
73
  it "should have an empty array for new_entries" do
@@ -0,0 +1,30 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
+
3
+ describe Myzofeedtosis::Result do
4
+ before do
5
+ @c = mock('curl')
6
+ @f = mock('feed')
7
+ @r = Myzofeedtosis::Result.new(@c, @f)
8
+ end
9
+
10
+ it "should raise an ArgumentError if the Curl object is nil" do
11
+ lambda {
12
+ Myzofeedtosis::Result.new(nil, nil)
13
+ }.should raise_error(ArgumentError)
14
+ end
15
+
16
+ it "should send author to the Feed object" do
17
+ @f.expects(:author)
18
+ @r.author
19
+ end
20
+
21
+ it "should send body_str to the curl object" do
22
+ @c.expects(:body_str)
23
+ @r.body_str
24
+ end
25
+
26
+ it "should return nil for author if the Feed is nil" do
27
+ r = Myzofeedtosis::Result.new(@c, nil)
28
+ r.author
29
+ end
30
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsl-myzofeedtosis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.2
4
+ version: 0.0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Leitgeb
@@ -74,6 +74,7 @@ files:
74
74
  - lib/extensions/core/array.rb
75
75
  - lib/extensions/core/hash.rb
76
76
  - lib/extensions/feed_normalizer/feed_instance_methods.rb
77
+ - lib/myzofeedtosis/result.rb
77
78
  - lib/myzofeedtosis/client.rb
78
79
  - lib/myzofeedtosis.rb
79
80
  - LICENSE
@@ -86,6 +87,7 @@ files:
86
87
  - spec/fixtures/xml/wooster.xml
87
88
  - spec/myzofeedtosis/client_spec.rb
88
89
  - spec/myzofeedtosis_spec.rb
90
+ - spec/myzofeedtosis/result_spec.rb
89
91
  - spec/spec_helper.rb
90
92
  has_rdoc: true
91
93
  homepage: http://github.com/jsl/myzofeedtosis
@@ -123,3 +125,4 @@ test_files:
123
125
  - spec/myzofeedtosis_spec.rb
124
126
  - spec/spec_helper.rb
125
127
  - spec/myzofeedtosis/client_spec.rb
128
+ - spec/myzofeedtosis/result_spec.rb