feed_cache 0.0.1
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/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README +0 -0
- data/Rakefile +5 -0
- data/feed_cache.gemspec +26 -0
- data/lib/feed_cache/fetcher.rb +40 -0
- data/lib/feed_cache/version.rb +3 -0
- data/lib/feed_cache.rb +37 -0
- data/spec/feed_cache_spec.rb +64 -0
- data/spec/fixtures/blog_feed.yaml +1416 -0
- data/spec/spec_helper.rb +1 -0
- metadata +125 -0
data/Gemfile
ADDED
data/README
ADDED
File without changes
|
data/Rakefile
ADDED
data/feed_cache.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "feed_cache/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "feed_cache"
|
7
|
+
s.version = FeedCache::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Brendon Murphy"]
|
10
|
+
s.email = ["xternal1+github@gmail.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{A thin wrapper over Feedzirra with injected caching}
|
13
|
+
s.description = s.summary
|
14
|
+
|
15
|
+
s.add_dependency "feedzirra", "~> 0.0.23"
|
16
|
+
|
17
|
+
s.add_development_dependency "rspec"
|
18
|
+
s.add_development_dependency "activesupport", "~> 2.3.5"
|
19
|
+
|
20
|
+
s.rubyforge_project = "feed_cache"
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'feedzirra'
|
3
|
+
|
4
|
+
module FeedCache
|
5
|
+
class Fetcher
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
attr_reader :url, :options
|
9
|
+
|
10
|
+
def_delegators :@fz_feed, :title, :last_modified, :entries
|
11
|
+
|
12
|
+
def cache
|
13
|
+
FeedCache.cache
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(url, options = {})
|
17
|
+
raise "cache must be set with FeedCache.cache=" unless cache
|
18
|
+
@url = url
|
19
|
+
@options = { :expires_in => FeedCache.default_expires_in }.merge options
|
20
|
+
end
|
21
|
+
|
22
|
+
def fetch
|
23
|
+
@fz_feed = cache.fetch(cache_key, options) do
|
24
|
+
Feedzirra::Feed.fetch_and_parse(url)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid_feed?
|
29
|
+
# Feedzirra returns fixnums in error conditions, so we
|
30
|
+
# need to type check.
|
31
|
+
@fz_feed && ! @fz_feed.is_a?(Fixnum)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def cache_key
|
37
|
+
url
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/feed_cache.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module FeedCache
|
2
|
+
DEFAULT_ENTRIES_LIMIT = 10
|
3
|
+
DEFAULT_EXPIRES_IN = 900
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :cache
|
7
|
+
attr_writer :default_entries_limit, :default_expires_in
|
8
|
+
|
9
|
+
def default_entries_limit
|
10
|
+
@default_entries_limit || DEFAULT_ENTRIES_LIMIT
|
11
|
+
end
|
12
|
+
|
13
|
+
def default_expires_in
|
14
|
+
@default_expires_in || DEFAULT_EXPIRES_IN
|
15
|
+
end
|
16
|
+
|
17
|
+
def configure(&block)
|
18
|
+
yield self
|
19
|
+
end
|
20
|
+
alias_method :config, :configure
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.fetch(url, options = {})
|
24
|
+
feed = FeedCache::Fetcher.new(url, options)
|
25
|
+
feed.fetch
|
26
|
+
feed.valid_feed? ? feed : nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.entries_for(url, options = {})
|
30
|
+
limit = options.delete(:limit) || default_entries_limit
|
31
|
+
feed = fetch(url, options)
|
32
|
+
(feed ? feed.entries : []).take(limit)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
require File.expand_path("feed_cache/fetcher", File.dirname(__FILE__))
|
37
|
+
require File.expand_path("feed_cache/version", File.dirname(__FILE__))
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_support'
|
3
|
+
|
4
|
+
# Examples are unforunately coupled to FeedZirra for now because it uses curb which is tough
|
5
|
+
# to mock, and the state of other feed parsers isn't compliant with our gemset
|
6
|
+
|
7
|
+
describe FeedCache do
|
8
|
+
let(:blog_url) { "http://blog.kajabi.com/rss.xml" }
|
9
|
+
let(:blog_feed) { YAML.load_file(File.join File.dirname(__FILE__), "./fixtures/blog_feed.yaml") }
|
10
|
+
let(:cache) { ActiveSupport::Cache::MemoryStore.new }
|
11
|
+
|
12
|
+
before do
|
13
|
+
Feedzirra::Feed.stub(:fetch_and_parse).with(blog_url).and_return(blog_feed)
|
14
|
+
FeedCache.configure do |fc|
|
15
|
+
fc.cache = cache
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "fetching a feed" do
|
20
|
+
context "for a valid feed grab" do
|
21
|
+
it "returns the feed with entries" do
|
22
|
+
feed = FeedCache.fetch(blog_url)
|
23
|
+
feed.entries.length.should == 20
|
24
|
+
end
|
25
|
+
|
26
|
+
it "stores the feed lookup in the cache" do
|
27
|
+
cache.exist?(blog_url).should be_false
|
28
|
+
FeedCache.fetch(blog_url)
|
29
|
+
cache.exist?(blog_url).should be_true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "for an invalid feed grab" do
|
34
|
+
it "returns nil" do
|
35
|
+
Feedzirra::Feed.stub(:fetch_and_parse).with(blog_url).and_return(404)
|
36
|
+
FeedCache.fetch(blog_url).should be_nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "getting just the entries for a feed" do
|
42
|
+
context "for a valid feed grab" do
|
43
|
+
it "returns the entries array" do
|
44
|
+
FeedCache.entries_for(blog_url).length.should == 10
|
45
|
+
end
|
46
|
+
|
47
|
+
it "takes a limit option to trucate entries" do
|
48
|
+
FeedCache.entries_for(blog_url, :limit => 3).length.should == 3
|
49
|
+
end
|
50
|
+
|
51
|
+
it "respects the default entries limit setting" do
|
52
|
+
FeedCache.default_entries_limit = 7
|
53
|
+
FeedCache.entries_for(blog_url).length.should == 7
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "for an invalid feed grab" do
|
58
|
+
it "returns an empty array" do
|
59
|
+
Feedzirra::Feed.stub(:fetch_and_parse).with(blog_url).and_return(404)
|
60
|
+
FeedCache.entries_for(blog_url).should == []
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|