Skip to content

Commit d1c9909

Browse files
author
Matt Swanson
committed
TDDing the feed parser stuff
1 parent be129b6 commit d1c9909

File tree

9 files changed

+140
-0
lines changed

9 files changed

+140
-0
lines changed

.rspec

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--colour

Gemfile

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ gem "sinatra-contrib", github: "sinatra/sinatra-contrib"
88
gem "rake"
99
gem "delayed_job_active_record"
1010

11+
gem "feedzirra", github: "pauldix/feedzirra"
12+
1113
group :production do
1214
gem "unicorn"
1315
gem "pg"

Gemfile.lock

+17
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
GIT
2+
remote: git://github.com/pauldix/feedzirra.git
3+
revision: 80cd35766e40ee3058db1c5c0c25448baeea4212
4+
specs:
5+
feedzirra (0.2.0.rc2)
6+
curb (~> 0.8.1)
7+
loofah (~> 1.2.1)
8+
nokogiri (~> 1.5.3)
9+
sax-machine (~> 0.2.0.rc1)
10+
111
GIT
212
remote: git://github.com/sinatra/sinatra-contrib.git
313
revision: 639acf8e8aec660cae5e4bfb5ed3d03132ed98e5
@@ -28,6 +38,7 @@ GEM
2838
backports (3.3.0)
2939
builder (3.0.4)
3040
coderay (1.0.9)
41+
curb (0.8.3)
3142
delayed_job (3.0.5)
3243
activesupport (~> 3.0)
3344
delayed_job_active_record (0.4.4)
@@ -37,8 +48,11 @@ GEM
3748
eventmachine (1.0.3)
3849
i18n (0.6.1)
3950
kgio (2.8.0)
51+
loofah (1.2.1)
52+
nokogiri (>= 1.4.4)
4053
method_source (0.8.1)
4154
multi_json (1.7.2)
55+
nokogiri (1.5.9)
4256
pg (0.15.0)
4357
pry (0.9.12)
4458
coderay (~> 1.0.5)
@@ -62,6 +76,8 @@ GEM
6276
rspec-expectations (2.13.0)
6377
diff-lcs (>= 1.1.3, < 2.0)
6478
rspec-mocks (2.13.0)
79+
sax-machine (0.2.0.rc1)
80+
nokogiri (~> 1.5.2)
6581
shotgun (0.9)
6682
rack (>= 1.0)
6783
sinatra (1.4.2)
@@ -87,6 +103,7 @@ PLATFORMS
87103

88104
DEPENDENCIES
89105
delayed_job_active_record
106+
feedzirra!
90107
pg
91108
pry
92109
rack-test

app/repositories/feed_repository.rb

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class FeedRepository
2+
def self.update_last_fetched(feed, timestamp)
3+
feed.last_fetched = timestamp
4+
feed.save
5+
end
6+
end

app/repositories/story_repository.rb

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class StoryRepository
2+
def self.add(entry, feed)
3+
4+
end
5+
end

app/tasks/fetch_feed.rb

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
require "feedzirra"
2+
require_relative "../repositories/story_repository"
3+
require_relative "../repositories/feed_repository"
4+
5+
class FetchFeed
6+
def initialize(feed, feed_parser = Feedzirra::Feed)
7+
@feed = feed
8+
@parser = feed_parser
9+
end
10+
11+
def fetch
12+
result = @parser.fetch_and_parse(@feed.url)
13+
14+
unless result.last_modified < @feed.last_fetched
15+
FeedRepository.update_last_fetched(@feed, result.last_modified)
16+
17+
result.entries.each do |entry|
18+
StoryRepository.add(entry, @feed) if is_new?(entry)
19+
end
20+
end
21+
22+
result
23+
end
24+
25+
private
26+
def is_new?(entry)
27+
entry.published > @feed.last_fetched
28+
end
29+
end

app/tasks/fetch_feeds.rb

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
require_relative "fetch_feed"
2+
3+
class FetchFeeds
4+
def initialize(feeds)
5+
@feeds = feeds
6+
end
7+
8+
def fetch_all
9+
@feeds.each do |feed|
10+
FetchFeed.new(feed).fetch
11+
end
12+
end
13+
end

spec/spec_helper.rb

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
ENV['RACK_ENV'] = 'test'
2+
3+
require "rspec"
4+
require "rack/test"
5+
require "pry"
6+
require "ostruct"
7+
require "date"
8+
9+
RSpec.configure do |config|
10+
config.include Rack::Test::Methods
11+
end
12+
13+
def app_require(file)
14+
require File.expand_path(File.join("app", file))
15+
end

spec/tasks/fetch_feed_spec.rb

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
require "spec_helper"
2+
app_require "tasks/fetch_feed"
3+
4+
class Feed < OpenStruct; end;
5+
6+
describe FetchFeed do
7+
let (:daring_fireball) {
8+
Feed.new(name: "Daring Fireball", url: "http://daringfireball.net/index.xml", last_fetched: Time.new(2013, 4, 5))
9+
}
10+
11+
describe "#fetch" do
12+
it "fetches the feed" do
13+
result = FetchFeed.new(daring_fireball).fetch
14+
result.title.should eq "Daring Fireball"
15+
result.entries.first.author.should eq "John Gruber"
16+
end
17+
18+
context "when no new posts have been added" do
19+
it "should not add any new posts" do
20+
fake_feed = stub(last_modified: Time.new(2012, 12, 31))
21+
parser = stub(fetch_and_parse: fake_feed)
22+
23+
StoryRepository.should_not_receive(:add)
24+
25+
FetchFeed.new(daring_fireball, parser).fetch
26+
end
27+
end
28+
29+
context "when new posts have been added" do
30+
let(:now) { Time.now }
31+
let(:new_story){ stub(published: now + 1) }
32+
let(:old_story) { stub(published: Time.new(2009, 4, 20)) }
33+
34+
let(:fake_feed) { stub(last_modified: now, entries: [new_story, old_story]) }
35+
let(:fake_parser) { stub(fetch_and_parse: fake_feed) }
36+
37+
it "should only add posts that are new" do
38+
StoryRepository.should_receive(:add).with(new_story, daring_fireball)
39+
StoryRepository.should_not_receive(:add).with(old_story, daring_fireball)
40+
41+
FetchFeed.new(daring_fireball, fake_parser).fetch
42+
end
43+
44+
it "should update the last fetched time for the feed" do
45+
FeedRepository.should_receive(:update_last_fetched)
46+
.with(daring_fireball, now)
47+
48+
FetchFeed.new(daring_fireball, fake_parser).fetch
49+
end
50+
end
51+
end
52+
end

0 commit comments

Comments
 (0)