feedcellar 0.5.0 → 0.6.0
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/NEWS.md +20 -0
- data/README.md +11 -1
- data/feedcellar.gemspec +2 -2
- data/lib/feedcellar/command.rb +26 -0
- data/lib/feedcellar/groonga_database.rb +57 -104
- data/lib/feedcellar/groonga_searcher.rb +50 -48
- data/lib/feedcellar/version.rb +1 -1
- data/test/fixtures/feeds.dump +0 -0
- data/test/fixtures/resources.dump +0 -0
- data/test/test-command.rb +130 -29
- data/test/test-groonga_database.rb +113 -0
- data/test/test-groonga_searcher.rb +103 -0
- metadata +14 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9702dd39c1fc809f99edbc966c15b775417246d8
|
4
|
+
data.tar.gz: aa5d0688709824dbd2fd7663b8b2ed35233381de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d94b13da24e5f1a2007f3ef03fc9a8e23f0bbec5654090c3e673a8d4c9ee18880bfdf26f01f794e310b158190b53585ef6e102df79f0666321e957d1119e779
|
7
|
+
data.tar.gz: f25da1c3fbfc51520f42c8c5ab4b54b601721791375feb9d23e025a45a56a4f2c5a59e166367920a0b1de0ef7c0f3f9c9a1ad0a81c0347fc82252721c761d78c
|
data/NEWS.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# NEWS
|
2
2
|
|
3
|
+
## 0.6.0: 2015-04-06
|
4
|
+
|
5
|
+
Support date related columns such as month.
|
6
|
+
|
7
|
+
### Changes
|
8
|
+
|
9
|
+
#### Improvements
|
10
|
+
|
11
|
+
* Supported to delete a feed by key.
|
12
|
+
* Supported delete feeds by resource key.
|
13
|
+
* Added delete command to delete feeds.
|
14
|
+
* Added month column for drilldown.
|
15
|
+
* Added wday column to Feed.
|
16
|
+
* Added year column to Feed.
|
17
|
+
* Added day column to Feeds table.
|
18
|
+
* search: Supported year option.
|
19
|
+
* search: Supported month option.
|
20
|
+
* Use Rroonga 5.0.0 or later for multiple column drilldown.
|
21
|
+
* Added reset command.
|
22
|
+
|
3
23
|
## 0.5.0: 2015-04-05
|
4
24
|
|
5
25
|
Extract interfaces to the other projects.
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# feedcellar - a feed reader
|
2
2
|
|
3
3
|
[](http://badge.fury.io/rb/feedcellar)
|
4
|
-
[](http://travis-ci.org/feedcellar/feedcellar)
|
5
5
|
|
6
6
|
Feedcellar is a full-text searchable RSS feed reader and data store.
|
7
7
|
|
@@ -57,6 +57,16 @@ Powered by [Groonga][] (via [Rroonga][]) with [Ruby][].
|
|
57
57
|
|
58
58
|
[Feedcellar::Curses](https://github.com/feedcellar/feedcellar-curses)
|
59
59
|
|
60
|
+
### Delete feeds
|
61
|
+
|
62
|
+
Delete a feed:
|
63
|
+
|
64
|
+
$ feedcellar delete URL
|
65
|
+
|
66
|
+
Delete feeds related registered resource URL:
|
67
|
+
|
68
|
+
$ feedcellar delete --resource URL
|
69
|
+
|
60
70
|
### Delete database
|
61
71
|
|
62
72
|
$ rm -r ~/.feedcellar
|
data/feedcellar.gemspec
CHANGED
@@ -30,14 +30,14 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.description = %q{Feedcellar is a full-text searchable RSS feed reader and data store by Groonga (via Rroonga) with Ruby.}
|
31
31
|
spec.summary = %q{Full-Text Searchable RSS Feed Reader by Groonga}
|
32
32
|
spec.homepage = "http://myokoym.net/feedcellar/"
|
33
|
-
spec.license = "LGPLv2.1
|
33
|
+
spec.license = "LGPLv2.1+"
|
34
34
|
|
35
35
|
spec.files = `git ls-files`.split($/)
|
36
36
|
spec.executables = spec.files.grep(%r{^bin/}) {|f| File.basename(f) }
|
37
37
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
38
38
|
spec.require_paths = ["lib"]
|
39
39
|
|
40
|
-
spec.add_runtime_dependency("rroonga", ">=
|
40
|
+
spec.add_runtime_dependency("rroonga", ">= 5.0.0")
|
41
41
|
spec.add_runtime_dependency("thor")
|
42
42
|
|
43
43
|
spec.add_development_dependency("test-unit")
|
data/lib/feedcellar/command.rb
CHANGED
@@ -108,6 +108,32 @@ module Feedcellar
|
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
|
+
desc "reset", "Reset all feeds for adding columns."
|
112
|
+
def reset
|
113
|
+
GroongaDatabase.new.open(@database_dir) do |database|
|
114
|
+
feeds = GroongaSearcher.search(database, nil)
|
115
|
+
feeds.each do |feed|
|
116
|
+
database.add(feed.resource.key,
|
117
|
+
feed.title,
|
118
|
+
feed.link,
|
119
|
+
feed.description,
|
120
|
+
feed.date)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
desc "delete URL", "Delete feeds by URL."
|
126
|
+
option :resource, :type => :boolean, :desc => "Delete registered URL related feeds"
|
127
|
+
def delete(url)
|
128
|
+
GroongaDatabase.new.open(@database_dir) do |database|
|
129
|
+
if options[:resource]
|
130
|
+
database.delete(:resource_key => url)
|
131
|
+
else
|
132
|
+
database.delete(url)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
111
137
|
desc "latest", "Show latest feeds by resources."
|
112
138
|
def latest
|
113
139
|
GroongaDatabase.new.open(@database_dir) do |database|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# class Feedcellar::GroongaDatabase
|
2
2
|
#
|
3
|
-
# Copyright (C) 2013-
|
3
|
+
# Copyright (C) 2013-2015 Masafumi Yokoyama <myokoym@gmail.com>
|
4
4
|
#
|
5
5
|
# This library is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -16,6 +16,7 @@
|
|
16
16
|
# License along with this library; if not, write to the Free Software
|
17
17
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
|
19
|
+
require "date"
|
19
20
|
require "groonga"
|
20
21
|
|
21
22
|
module Feedcellar
|
@@ -29,13 +30,7 @@ module Feedcellar
|
|
29
30
|
path = File.join(base_path, "feedcellar.db")
|
30
31
|
if File.exist?(path)
|
31
32
|
@database = Groonga::Database.open(path)
|
32
|
-
|
33
|
-
populate_schema
|
34
|
-
rescue Groonga::Schema::ColumnCreationWithDifferentOptions
|
35
|
-
# NOTE: migrate to feedcellar-0.3.0 from 0.2.2 or earlier.
|
36
|
-
populate_new_schema
|
37
|
-
transform_resources_key
|
38
|
-
end
|
33
|
+
populate_schema
|
39
34
|
else
|
40
35
|
FileUtils.mkdir_p(base_path)
|
41
36
|
populate(path)
|
@@ -54,15 +49,56 @@ module Feedcellar
|
|
54
49
|
end
|
55
50
|
|
56
51
|
def add(resource_key, title, link, description, date)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
52
|
+
columns = {
|
53
|
+
:resource => resources[resource_key],
|
54
|
+
:title => title,
|
55
|
+
:link => link,
|
56
|
+
:description => description,
|
57
|
+
:date => date,
|
58
|
+
}
|
59
|
+
if date
|
60
|
+
if feeds.have_column?(:year)
|
61
|
+
columns[:year] = date.year
|
62
|
+
end
|
63
|
+
if feeds.have_column?(:month)
|
64
|
+
columns[:month] = date.month
|
65
|
+
end
|
66
|
+
if feeds.have_column?(:day)
|
67
|
+
columns[:day] = date.day
|
68
|
+
end
|
69
|
+
if feeds.have_column?(:wday)
|
70
|
+
columns[:wday] = Date.new(date.year, date.month, date.day).wday
|
71
|
+
end
|
72
|
+
end
|
73
|
+
feeds.add(link, columns)
|
74
|
+
end
|
75
|
+
|
76
|
+
def delete(id_or_key_or_conditions)
|
77
|
+
if id_or_key_or_conditions.is_a?(Integer)
|
78
|
+
id = id_or_key_or_conditions
|
79
|
+
feeds.delete(id, :id => true)
|
80
|
+
elsif id_or_key_or_conditions.is_a?(String)
|
81
|
+
key = id_or_key_or_conditions
|
82
|
+
feeds.delete(key)
|
83
|
+
elsif id_or_key_or_conditions.is_a?(Hash)
|
84
|
+
conditions = id_or_key_or_conditions
|
85
|
+
feeds.delete do |record|
|
86
|
+
expression_builder = nil
|
87
|
+
conditions.each do |key, value|
|
88
|
+
case key
|
89
|
+
when :resource_key
|
90
|
+
record &= (record.resource._key == value)
|
91
|
+
else
|
92
|
+
raise ArgumentError,
|
93
|
+
"Not supported condition: <#{key}>"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
record
|
97
|
+
end
|
98
|
+
else
|
99
|
+
raise ArgumentError,
|
100
|
+
"Not supported type: <#{id_or_conditions.class}>"
|
101
|
+
end
|
66
102
|
end
|
67
103
|
|
68
104
|
def unregister(title_or_url)
|
@@ -126,6 +162,10 @@ module Feedcellar
|
|
126
162
|
table.short_text("title")
|
127
163
|
table.short_text("link")
|
128
164
|
table.text("description")
|
165
|
+
table.integer16("year")
|
166
|
+
table.integer8("month")
|
167
|
+
table.integer8("day")
|
168
|
+
table.integer8("wday")
|
129
169
|
table.time("date")
|
130
170
|
end
|
131
171
|
|
@@ -138,92 +178,5 @@ module Feedcellar
|
|
138
178
|
end
|
139
179
|
end
|
140
180
|
end
|
141
|
-
|
142
|
-
def populate_new_schema
|
143
|
-
populate_old_schema
|
144
|
-
add_new_column
|
145
|
-
migrate_value
|
146
|
-
delete_old_column
|
147
|
-
end
|
148
|
-
|
149
|
-
def transform_resources_key
|
150
|
-
resources.each do |resource|
|
151
|
-
next unless resource.xmlUrl
|
152
|
-
values = resource.attributes.reject do |key, value|
|
153
|
-
/^_/ =~ key
|
154
|
-
end
|
155
|
-
resources.add(resource.xmlUrl, values)
|
156
|
-
resources.delete(resource.id)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
def populate_old_schema
|
161
|
-
Groonga::Schema.define do |schema|
|
162
|
-
schema.create_table("Resources", :type => :hash) do |table|
|
163
|
-
table.text("text")
|
164
|
-
table.short_text("isComment")
|
165
|
-
table.short_text("isBreakpoint")
|
166
|
-
table.short_text("created")
|
167
|
-
table.short_text("category")
|
168
|
-
table.text("description")
|
169
|
-
table.short_text("url")
|
170
|
-
table.short_text("htmlUrl")
|
171
|
-
table.short_text("xmlUrl")
|
172
|
-
table.short_text("title")
|
173
|
-
table.short_text("version")
|
174
|
-
table.short_text("language")
|
175
|
-
end
|
176
|
-
|
177
|
-
schema.create_table("Feeds", :type => :hash) do |table|
|
178
|
-
table.short_text("resource")
|
179
|
-
table.short_text("title")
|
180
|
-
table.short_text("link")
|
181
|
-
table.text("description")
|
182
|
-
table.time("date")
|
183
|
-
end
|
184
|
-
|
185
|
-
schema.create_table("Terms",
|
186
|
-
:type => :patricia_trie,
|
187
|
-
:normalizer => "NormalizerAuto",
|
188
|
-
:default_tokenizer => "TokenBigram") do |table|
|
189
|
-
table.index("Feeds.title")
|
190
|
-
table.index("Feeds.description")
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def add_new_column
|
196
|
-
Groonga::Schema.define do |schema|
|
197
|
-
schema.change_table("Feeds") do |table|
|
198
|
-
table.reference("new_resource", "Resources")
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def migrate_value
|
204
|
-
feeds = Groonga["Feeds"]
|
205
|
-
resources = Groonga["Resources"]
|
206
|
-
tmp_resources = {}
|
207
|
-
resources.each do |resource|
|
208
|
-
tmp_resources[resource.xmlUrl] = resource.title
|
209
|
-
end
|
210
|
-
|
211
|
-
feeds.each do |feed|
|
212
|
-
feed["new_resource"] = resources[tmp_resources[feed.resource]]
|
213
|
-
feed["resource"] = nil
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
def delete_old_column
|
218
|
-
Groonga::Schema.define do |schema|
|
219
|
-
schema.change_table("Feeds") do |table|
|
220
|
-
table.remove_column("resource")
|
221
|
-
end
|
222
|
-
|
223
|
-
schema.change_table("Feeds") do |table|
|
224
|
-
table.rename_column("new_resource", "resource")
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
181
|
end
|
229
182
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# class Feedcellar::GroongaSearcher
|
2
2
|
#
|
3
|
-
# Copyright (C) 2013-
|
3
|
+
# Copyright (C) 2013-2015 Masafumi Yokoyama <myokoym@gmail.com>
|
4
4
|
#
|
5
5
|
# This library is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -19,56 +19,15 @@
|
|
19
19
|
module Feedcellar
|
20
20
|
class GroongaSearcher
|
21
21
|
class << self
|
22
|
-
def search(database, words, options)
|
22
|
+
def search(database, words, options={})
|
23
23
|
feeds = database.feeds
|
24
|
-
|
25
|
-
if (!words.nil? && !words.empty?) || options[:resource_id]
|
26
|
-
feeds = feeds.select do |feed|
|
27
|
-
expression = nil
|
28
|
-
words.each do |word|
|
29
|
-
sub_expression = (feed.title =~ word) |
|
30
|
-
(feed.description =~ word)
|
31
|
-
if expression.nil?
|
32
|
-
expression = sub_expression
|
33
|
-
else
|
34
|
-
expression &= sub_expression
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
if options[:mtime]
|
39
|
-
base_date = (Time.now - (options[:mtime] * 60 * 60 * 24))
|
40
|
-
mtime_expression = feed.date > base_date
|
41
|
-
if expression.nil?
|
42
|
-
expression = mtime_expression
|
43
|
-
else
|
44
|
-
expression &= mtime_expression
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
if options[:resource]
|
49
|
-
resource_expression = feed.resource =~ options[:resource]
|
50
|
-
if expression.nil?
|
51
|
-
expression = resource_expression
|
52
|
-
else
|
53
|
-
expression &= resource_expression
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
if options[:resource_id]
|
58
|
-
resource_expression = feed.resource._id == options[:resource_id]
|
59
|
-
if expression.nil?
|
60
|
-
expression = resource_expression
|
61
|
-
else
|
62
|
-
expression &= resource_expression
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
expression
|
67
|
-
end
|
68
|
-
end
|
24
|
+
selected_feeds = select_feeds(feeds, words, options)
|
69
25
|
|
70
26
|
order = options[:reverse] ? "ascending" : "descending"
|
71
|
-
sorted_feeds =
|
27
|
+
sorted_feeds = selected_feeds.sort([{
|
28
|
+
:key => "date",
|
29
|
+
:order => order,
|
30
|
+
}])
|
72
31
|
|
73
32
|
sorted_feeds
|
74
33
|
end
|
@@ -86,6 +45,49 @@ module Feedcellar
|
|
86
45
|
|
87
46
|
latest_feeds
|
88
47
|
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def select_feeds(feeds, words, options)
|
51
|
+
if (words.nil? || words.empty?) && options.empty?
|
52
|
+
return feeds
|
53
|
+
end
|
54
|
+
|
55
|
+
selected_feeds = feeds.select do |feed|
|
56
|
+
expression_builder = feed
|
57
|
+
|
58
|
+
if (!words.nil? && !words.empty?)
|
59
|
+
words.each do |word|
|
60
|
+
expression_builder &= (feed.title =~ word) |
|
61
|
+
(feed.description =~ word)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
if options[:mtime]
|
66
|
+
base_date = (Time.now - (options[:mtime] * 60 * 60 * 24))
|
67
|
+
expression_builder &= feed.date > base_date
|
68
|
+
end
|
69
|
+
|
70
|
+
if options[:resource]
|
71
|
+
expression_builder &= feed.resource =~ options[:resource]
|
72
|
+
end
|
73
|
+
|
74
|
+
if options[:resource_id]
|
75
|
+
expression_builder &= feed.resource._id == options[:resource_id]
|
76
|
+
end
|
77
|
+
|
78
|
+
if options[:year] && feeds.have_column?(:year)
|
79
|
+
expression_builder &= feed.year == options[:year]
|
80
|
+
end
|
81
|
+
|
82
|
+
if options[:month] && feeds.have_column?(:month)
|
83
|
+
expression_builder &= feed.month == options[:month]
|
84
|
+
end
|
85
|
+
|
86
|
+
expression_builder
|
87
|
+
end
|
88
|
+
|
89
|
+
selected_feeds
|
90
|
+
end
|
89
91
|
end
|
90
92
|
end
|
91
93
|
end
|
data/lib/feedcellar/version.rb
CHANGED
Binary file
|
Binary file
|
data/test/test-command.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# class CommandTest
|
4
4
|
#
|
5
|
-
# Copyright (C) 2013-
|
5
|
+
# Copyright (C) 2013-2015 Masafumi Yokoyama <myokoym@gmail.com>
|
6
6
|
#
|
7
7
|
# This library is free software; you can redistribute it and/or
|
8
8
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -25,26 +25,24 @@ require "feedcellar/command"
|
|
25
25
|
require "feedcellar/groonga_database"
|
26
26
|
|
27
27
|
class CommandTest < Test::Unit::TestCase
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
28
|
+
def setup
|
29
|
+
@tmpdir = File.join(File.dirname(__FILE__), "tmp")
|
30
|
+
FileUtils.rm_rf(@tmpdir)
|
31
|
+
FileUtils.mkdir_p(@tmpdir)
|
32
|
+
ENV["FEEDCELLAR_HOME"] = @tmpdir
|
33
|
+
@command = Feedcellar::Command.new
|
34
|
+
@database_dir = @command.database_dir
|
35
|
+
end
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
end
|
37
|
+
def teardown
|
38
|
+
FileUtils.rm_rf(@tmpdir)
|
41
39
|
end
|
42
40
|
|
43
41
|
def test_version
|
44
42
|
s = ""
|
45
43
|
io = StringIO.new(s)
|
46
44
|
$stdout = io
|
47
|
-
|
45
|
+
@command.version
|
48
46
|
assert_equal("#{Feedcellar::VERSION}\n", s)
|
49
47
|
$stdout = STDOUT
|
50
48
|
end
|
@@ -54,22 +52,39 @@ class CommandTest < Test::Unit::TestCase
|
|
54
52
|
s = ""
|
55
53
|
io = StringIO.new(s)
|
56
54
|
$stderr = io
|
57
|
-
assert_equal(1,
|
55
|
+
assert_equal(1, @command.register("hoge"))
|
58
56
|
assert_equal("ERROR: Invalid URL\n", s)
|
59
57
|
$stderr = STDERR
|
60
58
|
|
61
59
|
# confirm register command
|
62
|
-
|
63
|
-
|
64
|
-
|
60
|
+
resources = nil
|
61
|
+
resources_path = File.join(fixtures_dir, "resources.dump")
|
62
|
+
File.open(resources_path, "rb") do |file|
|
63
|
+
resources = Marshal.load(file)
|
64
|
+
end
|
65
|
+
mock(Feedcellar::Resource).parse("http://myokoym.github.io/entries.rss") {resources[0]}
|
66
|
+
mock(Feedcellar::Resource).parse("https://rubygems.org/gems/mister_fairy/versions.atom") {resources[1]}
|
67
|
+
@command.register("http://myokoym.github.io/entries.rss")
|
68
|
+
@command.register("https://rubygems.org/gems/mister_fairy/versions.atom")
|
69
|
+
Feedcellar::GroongaDatabase.new.open(@database_dir) do |database|
|
65
70
|
assert_equal(2, database.resources.size)
|
66
71
|
end
|
67
72
|
|
68
73
|
# confirm import command
|
69
|
-
file = File.join(
|
70
|
-
|
71
|
-
|
72
|
-
|
74
|
+
file = File.join(fixtures_dir, "subscriptions.xml")
|
75
|
+
@command.import(file)
|
76
|
+
|
77
|
+
feeds = nil
|
78
|
+
feeds_path = File.join(fixtures_dir, "feeds.dump")
|
79
|
+
File.open(feeds_path, "rb") do |file|
|
80
|
+
feeds = Marshal.load(file)
|
81
|
+
end
|
82
|
+
mock(Feedcellar::Feed).parse("http://myokoym.github.io/entries.rss") {feeds[0]}
|
83
|
+
mock(Feedcellar::Feed).parse("https://rubygems.org/gems/mister_fairy/versions.atom") {feeds[1]}
|
84
|
+
mock(Feedcellar::Feed).parse("http://blogs.yahoo.co.jp/mi807258/rss.xml") {feeds[2]}
|
85
|
+
@command.collect
|
86
|
+
|
87
|
+
Feedcellar::GroongaDatabase.new.open(@database_dir) do |database|
|
73
88
|
# NOTE: a tag of outline is not register.
|
74
89
|
assert_equal(3, database.resources.size)
|
75
90
|
assert_true(database.feeds.count > 0)
|
@@ -79,7 +94,7 @@ class CommandTest < Test::Unit::TestCase
|
|
79
94
|
s = ""
|
80
95
|
io = StringIO.new(s)
|
81
96
|
$stdout = io
|
82
|
-
|
97
|
+
@command.export
|
83
98
|
assert_equal(1, s.scan(/<opml/).size)
|
84
99
|
assert_equal(3, s.scan(/<outline/).size)
|
85
100
|
$stdout = STDOUT
|
@@ -88,17 +103,17 @@ class CommandTest < Test::Unit::TestCase
|
|
88
103
|
s = ""
|
89
104
|
io = StringIO.new(s)
|
90
105
|
$stdout = io
|
91
|
-
|
106
|
+
@command.search("ruby")
|
92
107
|
assert_true(s.size > 100)
|
93
108
|
$stdout = STDOUT
|
94
109
|
|
95
110
|
# confirm unregister command
|
96
|
-
|
97
|
-
Feedcellar::GroongaDatabase.new.open(
|
111
|
+
@command.unregister("my_letter")
|
112
|
+
Feedcellar::GroongaDatabase.new.open(@database_dir) do |database|
|
98
113
|
assert_equal(2, database.resources.size)
|
99
114
|
end
|
100
|
-
|
101
|
-
Feedcellar::GroongaDatabase.new.open(
|
115
|
+
@command.unregister("https://rubygems.org/gems/mister_fairy/versions.atom")
|
116
|
+
Feedcellar::GroongaDatabase.new.open(@database_dir) do |database|
|
102
117
|
assert_equal(1, database.resources.size)
|
103
118
|
end
|
104
119
|
|
@@ -106,8 +121,94 @@ class CommandTest < Test::Unit::TestCase
|
|
106
121
|
s = ""
|
107
122
|
io = StringIO.new(s)
|
108
123
|
$stdout = io
|
109
|
-
|
124
|
+
@command.latest
|
110
125
|
assert_true(s.size > 0)
|
111
126
|
$stdout = STDOUT
|
112
127
|
end
|
128
|
+
|
129
|
+
def test_reset
|
130
|
+
@database = Feedcellar::GroongaDatabase.new
|
131
|
+
@database.open(@database_dir)
|
132
|
+
Groonga["Resources"].add("http://my.today/atom")
|
133
|
+
@database.add("http://my.today/atom",
|
134
|
+
"What is Today?",
|
135
|
+
"http://my.today/201501",
|
136
|
+
"I don't know.",
|
137
|
+
nil)
|
138
|
+
assert_equal(0, @database.__send__(:feeds).first.year)
|
139
|
+
Groonga["Feeds"].add("http://my.today/201501",
|
140
|
+
{
|
141
|
+
:resource => "http://my.today/atom",
|
142
|
+
:title => "What is Today?",
|
143
|
+
:link => "http://my.today/201501",
|
144
|
+
:description => "January 1, 2015.",
|
145
|
+
:date => Time.new(2015, 1, 1),
|
146
|
+
})
|
147
|
+
@command.reset
|
148
|
+
assert_equal(2015, @database.__send__(:feeds).first.year)
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
def fixtures_dir
|
153
|
+
File.join(File.dirname(__FILE__), "fixtures")
|
154
|
+
end
|
155
|
+
|
156
|
+
class DeleteTest < self
|
157
|
+
def setup
|
158
|
+
super
|
159
|
+
resources = nil
|
160
|
+
resources_path = File.join(fixtures_dir, "resources.dump")
|
161
|
+
File.open(resources_path, "rb") do |file|
|
162
|
+
resources = Marshal.load(file)
|
163
|
+
end
|
164
|
+
mock(Feedcellar::Resource).parse("http://myokoym.github.io/entries.rss") {resources[0]}
|
165
|
+
@command.register("http://myokoym.github.io/entries.rss")
|
166
|
+
feeds = nil
|
167
|
+
feeds_path = File.join(fixtures_dir, "feeds.dump")
|
168
|
+
File.open(feeds_path, "rb") do |file|
|
169
|
+
feeds = Marshal.load(file)
|
170
|
+
end
|
171
|
+
mock(Feedcellar::Feed).parse("http://myokoym.github.io/entries.rss") {feeds[0]}
|
172
|
+
@command.collect
|
173
|
+
end
|
174
|
+
|
175
|
+
def teardown
|
176
|
+
super
|
177
|
+
$stdout = STDOUT
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_by_link
|
181
|
+
@str = ""
|
182
|
+
io = StringIO.new(@str)
|
183
|
+
$stdout = io
|
184
|
+
@command.search("ruby")
|
185
|
+
$stdout = STDOUT
|
186
|
+
assert_equal(13, @str.lines.size)
|
187
|
+
|
188
|
+
@command.delete("http://myokoym.github.com/entries/20131201/a0.html")
|
189
|
+
|
190
|
+
@str = ""
|
191
|
+
io = StringIO.new(@str)
|
192
|
+
$stdout = io
|
193
|
+
@command.search("ruby")
|
194
|
+
assert_equal(12, @str.lines.size)
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_by_resource_key
|
198
|
+
@str = ""
|
199
|
+
io = StringIO.new(@str)
|
200
|
+
$stdout = io
|
201
|
+
@command.search("ruby")
|
202
|
+
$stdout = STDOUT
|
203
|
+
assert_equal(13, @str.lines.size)
|
204
|
+
|
205
|
+
@command.delete(:resource_key => "http://myokoym.github.io/entries.rss")
|
206
|
+
|
207
|
+
@str = ""
|
208
|
+
io = StringIO.new(@str)
|
209
|
+
$stdout = io
|
210
|
+
@command.search("ruby")
|
211
|
+
assert_equal(0, @str.lines.size)
|
212
|
+
end
|
213
|
+
end
|
113
214
|
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# class GroongaDatabaseTest
|
4
|
+
#
|
5
|
+
# Copyright (C) 2015 Masafumi Yokoyama <myokoym@gmail.com>
|
6
|
+
#
|
7
|
+
# This library is free software; you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU Lesser General Public
|
9
|
+
# License as published by the Free Software Foundation; either
|
10
|
+
# version 2.1 of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This library is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public
|
18
|
+
# License along with this library; if not, write to the Free Software
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
20
|
+
|
21
|
+
require "feedcellar/groonga_database"
|
22
|
+
|
23
|
+
class GroongaDatabaseTest < Test::Unit::TestCase
|
24
|
+
def setup
|
25
|
+
@tmpdir = File.join(File.dirname(__FILE__), "tmp")
|
26
|
+
FileUtils.rm_rf(@tmpdir)
|
27
|
+
FileUtils.mkdir_p(@tmpdir)
|
28
|
+
ENV["FEEDCELLAR_HOME"] = @tmpdir
|
29
|
+
end
|
30
|
+
|
31
|
+
def teardown
|
32
|
+
FileUtils.rm_rf(@tmpdir)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_new
|
36
|
+
@database = Feedcellar::GroongaDatabase.new
|
37
|
+
assert_not_nil(@database)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_open
|
41
|
+
@database = Feedcellar::GroongaDatabase.new
|
42
|
+
assert_nil(@database.instance_variable_get(:@database))
|
43
|
+
@database.open(@tmpdir)
|
44
|
+
assert_not_nil(@database.instance_variable_get(:@database))
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_unregister
|
48
|
+
@database = Feedcellar::GroongaDatabase.new
|
49
|
+
@database.register("key", {:title => "Nikki"})
|
50
|
+
assert_equal(1, @database.__send__(:resources).size)
|
51
|
+
@database.unregister("Nikki")
|
52
|
+
assert_equal(0, @database.__send__(:resources).size)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_delete_by_key
|
56
|
+
@database = Feedcellar::GroongaDatabase.new
|
57
|
+
@database.open(@tmpdir)
|
58
|
+
@database.add("resource",
|
59
|
+
"Today's lunch",
|
60
|
+
"http://my.nikki/123",
|
61
|
+
"So cute.",
|
62
|
+
Time.now)
|
63
|
+
assert_equal(1, @database.__send__(:feeds).size)
|
64
|
+
@database.delete("http://my.nikki/123")
|
65
|
+
assert_equal(0, @database.__send__(:feeds).size)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_delete_by_resource_key
|
69
|
+
@database = Feedcellar::GroongaDatabase.new
|
70
|
+
@database.open(@tmpdir)
|
71
|
+
@database.register("http://my.diary/rss", {:title => "My Diary"})
|
72
|
+
2.times do |i|
|
73
|
+
@database.add("http://my.diary/rss",
|
74
|
+
"Today's dinnar",
|
75
|
+
"http://my.diary/#{i}",
|
76
|
+
"So mad.",
|
77
|
+
Time.now)
|
78
|
+
end
|
79
|
+
assert_equal(2, @database.__send__(:feeds).size)
|
80
|
+
@database.delete(:resource_key => "http://my.diary/rss")
|
81
|
+
assert_equal(0, @database.__send__(:feeds).size)
|
82
|
+
end
|
83
|
+
|
84
|
+
class AddTest < self
|
85
|
+
def setup
|
86
|
+
super
|
87
|
+
@database = Feedcellar::GroongaDatabase.new
|
88
|
+
@database.open(@tmpdir)
|
89
|
+
@database.add("http://my.monthly/atom",
|
90
|
+
"What is month Today?",
|
91
|
+
"http://my.monthly/201504",
|
92
|
+
"April...f...",
|
93
|
+
Time.new(2015, 4, 5))
|
94
|
+
@feed = @database.__send__(:feeds).first
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_year
|
98
|
+
assert_equal(2015, @feed.year)
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_month
|
102
|
+
assert_equal(4, @feed.month)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_day
|
106
|
+
assert_equal(5, @feed.day)
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_wday
|
110
|
+
assert_equal(0, @feed.wday)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# class GroongaSearcherTest
|
4
|
+
#
|
5
|
+
# Copyright (C) 2015 Masafumi Yokoyama <myokoym@gmail.com>
|
6
|
+
#
|
7
|
+
# This library is free software; you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU Lesser General Public
|
9
|
+
# License as published by the Free Software Foundation; either
|
10
|
+
# version 2.1 of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This library is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public
|
18
|
+
# License along with this library; if not, write to the Free Software
|
19
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
20
|
+
|
21
|
+
require "feedcellar/groonga_database"
|
22
|
+
require "feedcellar/groonga_searcher"
|
23
|
+
|
24
|
+
class GroongaSearcherTest < Test::Unit::TestCase
|
25
|
+
def setup
|
26
|
+
@tmpdir = File.join(File.dirname(__FILE__), "tmp")
|
27
|
+
FileUtils.rm_rf(@tmpdir)
|
28
|
+
FileUtils.mkdir_p(@tmpdir)
|
29
|
+
ENV["FEEDCELLAR_HOME"] = @tmpdir
|
30
|
+
@database = Feedcellar::GroongaDatabase.new
|
31
|
+
@database.open(@tmpdir)
|
32
|
+
end
|
33
|
+
|
34
|
+
def teardown
|
35
|
+
@database.close
|
36
|
+
FileUtils.rm_rf(@tmpdir)
|
37
|
+
end
|
38
|
+
|
39
|
+
class SearchTest < self
|
40
|
+
def setup
|
41
|
+
super
|
42
|
+
resource_key = "http://null.myokoym.net/rss"
|
43
|
+
title = "Test"
|
44
|
+
link = "http://null.myokoym.net/"
|
45
|
+
description = "The site is fiction."
|
46
|
+
date = Time.new(2014, 2, 5)
|
47
|
+
@database.add(resource_key, title, link, description, date)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_all_records
|
51
|
+
feeds = Feedcellar::GroongaSearcher.search(@database, [])
|
52
|
+
assert_equal(1, feeds.size)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_found
|
56
|
+
words = []
|
57
|
+
words << "fiction"
|
58
|
+
feeds = Feedcellar::GroongaSearcher.search(@database, words)
|
59
|
+
assert_equal(1, feeds.size)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_year_found
|
63
|
+
options = {
|
64
|
+
:year => 2014,
|
65
|
+
}
|
66
|
+
feeds = Feedcellar::GroongaSearcher.search(@database, [], options)
|
67
|
+
assert_equal(1, feeds.size)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_year_not_found
|
71
|
+
options = {
|
72
|
+
:year => 2013,
|
73
|
+
}
|
74
|
+
feeds = Feedcellar::GroongaSearcher.search(@database, [], options)
|
75
|
+
assert_equal(0, feeds.size)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_month_found
|
79
|
+
options = {
|
80
|
+
:month => 2,
|
81
|
+
}
|
82
|
+
feeds = Feedcellar::GroongaSearcher.search(@database, [], options)
|
83
|
+
assert_equal(1, feeds.size)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_month_not_found
|
87
|
+
options = {
|
88
|
+
:year => 3,
|
89
|
+
}
|
90
|
+
feeds = Feedcellar::GroongaSearcher.search(@database, [], options)
|
91
|
+
assert_equal(0, feeds.size)
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_year_and_month
|
95
|
+
options = {
|
96
|
+
:year => 2014,
|
97
|
+
:month => 2,
|
98
|
+
}
|
99
|
+
feeds = Feedcellar::GroongaSearcher.search(@database, [], options)
|
100
|
+
assert_equal(1, feeds.size)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: feedcellar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masafumi Yokoyama
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rroonga
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 5.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 5.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: thor
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,13 +136,17 @@ files:
|
|
136
136
|
- lib/feedcellar/opml.rb
|
137
137
|
- lib/feedcellar/resource.rb
|
138
138
|
- lib/feedcellar/version.rb
|
139
|
+
- test/fixtures/feeds.dump
|
140
|
+
- test/fixtures/resources.dump
|
139
141
|
- test/fixtures/subscriptions.xml
|
140
142
|
- test/run-test.rb
|
141
143
|
- test/test-command.rb
|
144
|
+
- test/test-groonga_database.rb
|
145
|
+
- test/test-groonga_searcher.rb
|
142
146
|
- test/test-opml.rb
|
143
147
|
homepage: http://myokoym.net/feedcellar/
|
144
148
|
licenses:
|
145
|
-
- LGPLv2.1
|
149
|
+
- LGPLv2.1+
|
146
150
|
metadata: {}
|
147
151
|
post_install_message:
|
148
152
|
rdoc_options: []
|
@@ -160,13 +164,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
160
164
|
version: '0'
|
161
165
|
requirements: []
|
162
166
|
rubyforge_project:
|
163
|
-
rubygems_version: 2.
|
167
|
+
rubygems_version: 2.4.5
|
164
168
|
signing_key:
|
165
169
|
specification_version: 4
|
166
170
|
summary: Full-Text Searchable RSS Feed Reader by Groonga
|
167
171
|
test_files:
|
172
|
+
- test/fixtures/feeds.dump
|
173
|
+
- test/fixtures/resources.dump
|
168
174
|
- test/fixtures/subscriptions.xml
|
169
175
|
- test/run-test.rb
|
170
176
|
- test/test-command.rb
|
177
|
+
- test/test-groonga_database.rb
|
178
|
+
- test/test-groonga_searcher.rb
|
171
179
|
- test/test-opml.rb
|
172
|
-
has_rdoc:
|