pavlov_rss 0.0.3 → 0.0.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.
- 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
|