pavlov_rss 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/pavlov_rss/reader.rb +16 -22
- data/lib/pavlov_rss/version.rb +1 -1
- data/spec/lib/pavlov_rss/reader_spec.rb +189 -171
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35a29663a549afb08c61d6f4b88619c588d6c172
|
4
|
+
data.tar.gz: 9b74530d53d962b0f2c9d50c9558a73ea15f8b5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff7e6ae7cf8950adc99ae1efacd8a043dc35a17fcda5b172185c7645fef399204a78fa02f466b3f7e2c106c04afb9ae1da1a9592af112d3d3c12cf25d719b748
|
7
|
+
data.tar.gz: a58856d9e2bb5763a98a1eebd3740cfabc2a4e9b2ec5148035c446ae5462aeb4c7ae01e46bf416ec9abb844f0c33d425a2d9221fcdb02ac53d3c5b1ca08d30cb
|
data/Gemfile.lock
CHANGED
data/lib/pavlov_rss/reader.rb
CHANGED
@@ -4,42 +4,36 @@ require 'active_support/core_ext'
|
|
4
4
|
|
5
5
|
module PavlovRss
|
6
6
|
class Reader
|
7
|
-
def
|
8
|
-
@
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
url_or_lambda
|
14
|
-
end
|
15
|
-
end
|
7
|
+
def opener &opener
|
8
|
+
@opener = opener
|
9
|
+
end
|
10
|
+
|
11
|
+
def fetch
|
12
|
+
hash_to_item(rss_to_hash(Nokogiri.XML(@opener.call)))
|
16
13
|
end
|
17
14
|
|
18
15
|
def check
|
19
|
-
now =
|
16
|
+
now = fetch
|
20
17
|
@prev ||= now
|
21
|
-
result =
|
22
|
-
new_items p, n
|
23
|
-
end
|
18
|
+
result = now - @prev
|
24
19
|
@prev = now
|
25
20
|
return result
|
26
21
|
end
|
27
22
|
|
28
|
-
def
|
29
|
-
|
23
|
+
def rss_to_hash rss
|
24
|
+
Hash.from_xml(rss.to_xml)
|
25
|
+
end
|
26
|
+
|
27
|
+
def hash_to_item hash
|
30
28
|
result = case
|
31
|
-
when
|
32
|
-
|
29
|
+
when hash.has_key?('rss')
|
30
|
+
hash['rss']['channel']['item']
|
33
31
|
when value.has_key?('feed')
|
34
|
-
|
32
|
+
hash['feed']['entry']
|
35
33
|
end
|
36
34
|
result ||= []
|
37
35
|
return result if result.is_a? Array
|
38
36
|
return [result]
|
39
37
|
end
|
40
|
-
|
41
|
-
def new_items lhs, rhs
|
42
|
-
item_to_json(rhs) - item_to_json(lhs)
|
43
|
-
end
|
44
38
|
end
|
45
39
|
end
|
data/lib/pavlov_rss/version.rb
CHANGED
@@ -1,185 +1,203 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'pavlov_rss'
|
3
3
|
require 'nokogiri'
|
4
|
-
require 'fake_web'
|
5
4
|
|
6
5
|
describe PavlovRss::Reader do
|
7
|
-
|
8
|
-
|
6
|
+
describe '#hash_to_item' do
|
7
|
+
subject { described_class.new.hash_to_item(hash) }
|
8
|
+
|
9
|
+
describe do
|
10
|
+
let(:hash) do
|
11
|
+
{'rss' => {'channel' => {'item' => []}}}
|
12
|
+
end
|
13
|
+
it { should be_empty }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe do
|
17
|
+
let(:hash) do
|
18
|
+
{'rss' => {'channel' => {'item' =>
|
19
|
+
{'title' => 'title1'}
|
20
|
+
}}}
|
21
|
+
end
|
22
|
+
it { should have(1).item }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe do
|
26
|
+
let(:hash) do
|
27
|
+
{'rss' => {'channel' => {'item' => [
|
28
|
+
{'title' => 'title1'},
|
29
|
+
{'title' => 'title2'},
|
30
|
+
]}}}
|
31
|
+
end
|
32
|
+
it { should have(2).items }
|
33
|
+
end
|
9
34
|
end
|
10
35
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
describe
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
it "returns new items" do
|
43
|
-
FakeWeb.register_uri(:get, @url, [
|
44
|
-
{body: feed('rss0.xml')},
|
45
|
-
{body: feed('rss1.xml')},
|
46
|
-
{body: feed('rss2.xml')},
|
47
|
-
{body: feed('rss3.xml')},
|
48
|
-
{body: feed('rss4.xml')},
|
49
|
-
{body: feed('rss5.xml')},
|
50
|
-
])
|
51
|
-
@reader.check
|
52
|
-
@reader.check.should == [[
|
53
|
-
{
|
54
|
-
"title"=>"title1",
|
55
|
-
"link"=>"http://example.com/title1",
|
56
|
-
"description"=>"description1"
|
57
|
-
}]]
|
58
|
-
@reader.check.should == [[
|
59
|
-
{
|
60
|
-
"title"=>"title2",
|
61
|
-
"link"=>"http://example.com/title2",
|
62
|
-
"description"=>"description2"
|
63
|
-
}]]
|
64
|
-
@reader.check.should == [[
|
65
|
-
{
|
66
|
-
"title"=>"title3",
|
67
|
-
"link"=>"http://example.com/title3",
|
68
|
-
"description"=>"description3"
|
69
|
-
}]]
|
70
|
-
@reader.check.should == [[
|
71
|
-
{
|
72
|
-
"title"=>"title4",
|
73
|
-
"link"=>"http://example.com/title4",
|
74
|
-
"description"=>"description4"
|
75
|
-
}]]
|
76
|
-
@reader.check.should == [[
|
77
|
-
{
|
78
|
-
"title"=>"title5",
|
79
|
-
"link"=>"http://example.com/title5",
|
80
|
-
"description"=>"description5"
|
81
|
-
}]]
|
82
|
-
@reader.check.should == [[]]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
describe "#new_items" do
|
87
|
-
it "returns empty with same rss" do
|
88
|
-
rss1 = Nokogiri.XML(feed('rss1.xml'))
|
89
|
-
rss2 = Nokogiri.XML(feed('rss1.xml'))
|
90
|
-
items = @reader.new_items rss1, rss2
|
91
|
-
items.should == []
|
92
|
-
end
|
93
|
-
|
94
|
-
it "returns empty with not same rss" do
|
95
|
-
rss1 = Nokogiri.XML(feed('rss1.xml'))
|
96
|
-
rss2 = Nokogiri.XML(feed('rss2.xml'))
|
97
|
-
items = @reader.new_items rss1, rss2
|
98
|
-
|
99
|
-
items.should == [
|
100
|
-
{
|
101
|
-
"title"=>"title2",
|
102
|
-
"link"=>"http://example.com/title2",
|
103
|
-
"description"=>"description2"
|
104
|
-
}]
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
describe "#item_to_json" do
|
109
|
-
it "works" do
|
110
|
-
rss = Nokogiri.XML(feed('rss1.xml'))
|
111
|
-
result = @reader.item_to_json rss
|
112
|
-
result.should == [
|
113
|
-
{
|
114
|
-
"title"=>"title1",
|
115
|
-
"link"=>"http://example.com/title1",
|
116
|
-
"description"=>"description1"
|
117
|
-
}]
|
118
|
-
end
|
119
|
-
it "works on 0-items rss" do
|
120
|
-
rss = Nokogiri.XML(feed('rss0.xml'))
|
121
|
-
result = @reader.item_to_json rss
|
122
|
-
result.should == []
|
123
|
-
end
|
124
|
-
it "works on atom" do
|
125
|
-
atom = Nokogiri.XML(feed('atom.xml'))
|
126
|
-
result = @reader.item_to_json atom
|
127
|
-
result.should == [{
|
128
|
-
"title"=>"title",
|
129
|
-
"id"=>"tag_string",
|
130
|
-
"content"=>"content"
|
131
|
-
}]
|
36
|
+
describe '#rss_to_hash' do
|
37
|
+
shared_examples 'hashfied rss', rss_to_hash: :works do
|
38
|
+
subject { described_class.new.rss_to_hash(Nokogiri.XML(rss)) }
|
39
|
+
it { should == expected }
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'works on general rss', rss_to_hash: :works do
|
43
|
+
let(:rss) { feed('rss2.xml') }
|
44
|
+
let(:expected) do
|
45
|
+
{'rss'=>{'version'=>'2.0', 'channel'=>{'title'=>'title', 'link'=>'http://example.com', 'description'=>'description', 'item'=>[{'title'=>'title2', 'link'=>'http://example.com/title2', 'description'=>'description2'}, {'title'=>'title1', 'link'=>'http://example.com/title1', 'description'=>'description1'}]}}}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'works on 1-item rss', rss_to_hash: :works do
|
50
|
+
let(:rss) { feed('rss1.xml') }
|
51
|
+
let(:expected) do
|
52
|
+
{'rss' => {'version'=>'2.0', 'channel'=>{'title'=>'title', 'link'=>'http://example.com', 'description'=>'description', 'item'=>{'title'=>'title1', 'link'=>'http://example.com/title1', 'description'=>'description1'}}}}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'works on 0-item rss', rss_to_hash: :works do
|
57
|
+
let(:rss) { feed('rss0.xml') }
|
58
|
+
let(:expected) do
|
59
|
+
{'rss' => {'version'=>'2.0', 'channel'=>{'title'=>'title', 'link'=>'http://example.com', 'description'=>'description'}}}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'works on atom', rss_to_hash: :works do
|
64
|
+
let(:rss) { feed('atom.xml') }
|
65
|
+
let(:expected) do
|
66
|
+
{'feed'=>{'xmlns'=>'http://www.w3.org/2005/Atom', 'entry'=>{'title'=>'title', 'id'=>'tag_string', 'content'=>'content'}}}
|
132
67
|
end
|
133
68
|
end
|
134
69
|
end
|
135
70
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
end
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
"title"=>"title2",
|
161
|
-
"link"=>"http://example.com/
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
{
|
172
|
-
"title"=>"
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
71
|
+
describe '#fetch' do
|
72
|
+
shared_examples 'fetched rss', fetch: :works do
|
73
|
+
before { subject.opener { rss } }
|
74
|
+
its(:fetch) { should == expected }
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'works with rss0.xml', fetch: :works do
|
78
|
+
let(:rss) { feed('rss0.xml') }
|
79
|
+
let(:expected) { [] }
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'works with rss1.xml', fetch: :works do
|
83
|
+
let(:rss) { feed('rss1.xml') }
|
84
|
+
let(:expected) do
|
85
|
+
[
|
86
|
+
{"title"=>"title1", "link"=>"http://example.com/title1", "description"=>"description1"},
|
87
|
+
]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'works with rss2.xml', fetch: :works do
|
92
|
+
let(:rss) { feed('rss2.xml') }
|
93
|
+
let(:expected) do
|
94
|
+
[
|
95
|
+
{"title"=>"title2", "link"=>"http://example.com/title2", "description"=>"description2"},
|
96
|
+
{"title"=>"title1", "link"=>"http://example.com/title1", "description"=>"description1"},
|
97
|
+
]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'works with rss3.xml', fetch: :works do
|
102
|
+
let(:rss) { feed('rss3.xml') }
|
103
|
+
let(:expected) do
|
104
|
+
[
|
105
|
+
{"title"=>"title3", "link"=>"http://example.com/title3", "description"=>"description3"},
|
106
|
+
{"title"=>"title2", "link"=>"http://example.com/title2", "description"=>"description2"},
|
107
|
+
{"title"=>"title1", "link"=>"http://example.com/title1", "description"=>"description1"},
|
108
|
+
]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe 'works with rss4.xml', fetch: :works do
|
113
|
+
let(:rss) { feed('rss4.xml') }
|
114
|
+
let(:expected) do
|
115
|
+
[
|
116
|
+
{"title"=>"title4", "link"=>"http://example.com/title4", "description"=>"description4"},
|
117
|
+
{"title"=>"title3", "link"=>"http://example.com/title3", "description"=>"description3"},
|
118
|
+
{"title"=>"title2", "link"=>"http://example.com/title2", "description"=>"description2"},
|
119
|
+
]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe 'works with rss5.xml', fetch: :works do
|
124
|
+
let(:rss) { feed('rss5.xml') }
|
125
|
+
let(:expected) do
|
126
|
+
[
|
127
|
+
{"title"=>"title5", "link"=>"http://example.com/title5", "description"=>"description5"},
|
128
|
+
{"title"=>"title4", "link"=>"http://example.com/title4", "description"=>"description4"},
|
129
|
+
{"title"=>"title3", "link"=>"http://example.com/title3", "description"=>"description3"},
|
130
|
+
]
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '#check' do
|
136
|
+
shared_examples 'check works', check: :works do
|
137
|
+
before do
|
138
|
+
subject.stub(:fetch).and_return(*fetches)
|
139
|
+
subject.check.should be_empty
|
140
|
+
end
|
141
|
+
its(:check) { should == expected }
|
142
|
+
end
|
143
|
+
|
144
|
+
describe 'works with empty items', check: :works do
|
145
|
+
let(:fetches) { [[], []] }
|
146
|
+
let(:expected) { [] }
|
147
|
+
end
|
148
|
+
|
149
|
+
describe 'works with same items', check: :works do
|
150
|
+
let(:fetches) do
|
151
|
+
[
|
152
|
+
[{'title' => '1'}],
|
153
|
+
[{'title' => '1'}],
|
154
|
+
]
|
155
|
+
end
|
156
|
+
let(:expected) { [] }
|
157
|
+
end
|
158
|
+
|
159
|
+
describe 'works with added items', check: :works do
|
160
|
+
let(:fetches) do
|
161
|
+
[
|
162
|
+
[],
|
163
|
+
[{'title' => '1'}],
|
164
|
+
]
|
165
|
+
end
|
166
|
+
let(:expected) { [{'title' => '1'}] }
|
167
|
+
end
|
168
|
+
|
169
|
+
describe 'works with removed items', check: :works do
|
170
|
+
let(:fetches) do
|
171
|
+
[
|
172
|
+
[{'title' => '1'}],
|
173
|
+
[],
|
174
|
+
]
|
175
|
+
end
|
176
|
+
let(:expected) { [] }
|
177
|
+
end
|
178
|
+
|
179
|
+
describe 'works with various items', check: :works do
|
180
|
+
let(:fetches) do
|
181
|
+
[
|
182
|
+
[
|
183
|
+
{'title' => 'static1'},
|
184
|
+
{'title' => 'static2'},
|
185
|
+
{'title' => 'remove1'},
|
186
|
+
{'title' => 'remove2'},
|
187
|
+
],
|
188
|
+
[
|
189
|
+
{'title' => 'static1'},
|
190
|
+
{'title' => 'static2'},
|
191
|
+
{'title' => 'add1'},
|
192
|
+
{'title' => 'add2'},
|
193
|
+
],
|
194
|
+
]
|
195
|
+
end
|
196
|
+
let(:expected) do
|
197
|
+
[
|
198
|
+
{'title' => 'add1'},
|
199
|
+
{'title' => 'add2'},
|
200
|
+
]
|
183
201
|
end
|
184
202
|
end
|
185
203
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pavlov_rss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Minwoo Lee
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-03-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|