grn_mini 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,14 +1,17 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require 'minitest_helper'
2
3
 
3
4
  class TestGrnMiniHash < MiniTest::Unit::TestCase
4
5
  def test_initialize
5
- Dir.mktmpdir do |dir|
6
- hash = GrnMini::Hash.new(File.join(dir, "test.db"))
6
+ GrnMini::tmpdb do
7
+ hash = GrnMini::Hash.new
7
8
  end
8
9
  end
9
10
 
10
11
  def test_add
11
- GrnMini::Hash.tmpdb do |hash|
12
+ GrnMini::tmpdb do
13
+ hash = GrnMini::Hash.new
14
+
12
15
  hash.add("aaa", text:"aaa", number:1)
13
16
  assert_equal 1, hash.size
14
17
 
@@ -19,12 +22,14 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
19
22
  end
20
23
 
21
24
  def test_select
22
- GrnMini::Hash.tmpdb do |hash|
25
+ GrnMini::tmpdb do
26
+ hash = GrnMini::Hash.new
27
+
23
28
  hash["a"] = {text:"aaa", number:1}
24
29
  hash["b"] = {text:"bbb", number:2}
25
30
  hash["c"] = {text:"ccc", number:3}
26
31
 
27
- results = hash.select("bb")
32
+ results = hash.select("text:@bb")
28
33
 
29
34
  assert_equal 1, results.size
30
35
  assert_equal "b", results.first.key.key
@@ -33,13 +38,15 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
33
38
  end
34
39
 
35
40
  def test_select2
36
- GrnMini::Hash.tmpdb do |hash|
41
+ GrnMini::tmpdb do
42
+ hash = GrnMini::Hash.new
43
+
37
44
  hash["a"] = {text:"aaa", number:1}
38
45
  hash["b"] = {text:"bbb", number:2}
39
46
  hash["c"] = {text:"bbb", number:20}
40
47
  hash["d"] = {text:"ccc", number:3}
41
48
 
42
- results = hash.select("bb number:<10")
49
+ results = hash.select("text:@bb number:<10")
43
50
 
44
51
  assert_equal 1, results.size
45
52
  assert_equal "b", results.first.key.key
@@ -49,19 +56,21 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
49
56
  end
50
57
 
51
58
  def test_size
52
- GrnMini::Hash.tmpdb do |hash|
59
+ GrnMini::tmpdb do
60
+ hash = GrnMini::Hash.new
61
+
53
62
  assert_equal 0, hash.size
54
- assert_equal 0, hash.length
55
63
 
56
64
  hash["a"] = {text:"aaa", number:1}
57
65
  hash["b"] = {text:"bbb", number:2}
58
66
  assert_equal 2, hash.size
59
- assert_equal 2, hash.length
60
67
  end
61
68
  end
62
69
 
63
70
  def test_empty?
64
- GrnMini::Hash.tmpdb do |hash|
71
+ GrnMini::tmpdb do
72
+ hash = GrnMini::Hash.new
73
+
65
74
  assert_equal true, hash.empty?
66
75
 
67
76
  hash["a"] = {text:"aaa", number:1}
@@ -70,7 +79,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
70
79
  end
71
80
 
72
81
  def test_each
73
- GrnMini::Hash.tmpdb do |hash|
82
+ GrnMini::tmpdb do
83
+ hash = GrnMini::Hash.new
84
+
74
85
  hash["c"] = {text:"ccc", number:3}
75
86
  hash["a"] = {text:"aaa", number:1}
76
87
  hash["b"] = {text:"bbb", number:2}
@@ -86,7 +97,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
86
97
  end
87
98
 
88
99
  def test_read_by_key
89
- GrnMini::Hash.tmpdb do |hash|
100
+ GrnMini::tmpdb do
101
+ hash = GrnMini::Hash.new
102
+
90
103
  hash["a"] = {text:"aaa", number:1}
91
104
  hash["b"] = {text:"bbb", number:2}
92
105
  hash["c"] = {text:"ccc", number:3}
@@ -99,7 +112,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
99
112
  end
100
113
 
101
114
  def test_write_by_key
102
- GrnMini::Hash.tmpdb do |hash|
115
+ GrnMini::tmpdb do
116
+ hash = GrnMini::Hash.new
117
+
103
118
  hash["a"] = {text:"aaa", number:1}
104
119
  hash["b"] = {text:"bbb", number:2}
105
120
  hash["c"] = {text:"ccc", number:3}
@@ -116,7 +131,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
116
131
  end
117
132
 
118
133
  def test_delete_by_id
119
- GrnMini::Hash.tmpdb do |hash|
134
+ GrnMini::tmpdb do
135
+ hash = GrnMini::Hash.new
136
+
120
137
  hash["a"] = {text:"aaa", number:1}
121
138
  hash["b"] = {text:"bbb", number:2}
122
139
  hash["c"] = {text:"ccc", number:3}
@@ -133,7 +150,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
133
150
  end
134
151
 
135
152
  def test_delete_by_block
136
- GrnMini::Hash.tmpdb do |hash|
153
+ GrnMini::tmpdb do
154
+ hash = GrnMini::Hash.new
155
+
137
156
  hash["a"] = {text:"aaa", number:1}
138
157
  hash["b"] = {text:"bbb", number:2}
139
158
  hash["c"] = {text:"ccc", number:3}
@@ -149,7 +168,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
149
168
  end
150
169
 
151
170
  def test_float_column
152
- GrnMini::Hash.tmpdb do |hash|
171
+ GrnMini::tmpdb do
172
+ hash = GrnMini::Hash.new
173
+
153
174
  hash["a"] = {text:"aaaa", float: 1.5}
154
175
  hash["b"] = {text:"bbbb", float: 2.5}
155
176
  hash["c"] = {text:"cccc", float: 3.5}
@@ -162,7 +183,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
162
183
  end
163
184
 
164
185
  def test_time_column
165
- GrnMini::Hash.tmpdb do |hash|
186
+ GrnMini::tmpdb do
187
+ hash = GrnMini::Hash.new
188
+
166
189
  hash["a"] = {text:"aaaa", timestamp: Time.new(2013)} # 2013-01-01
167
190
  hash["b"] = {text:"bbbb", timestamp: Time.new(2014)} # 2014-01-01
168
191
  hash["c"] = {text:"cccc", timestamp: Time.new(2015)} # 2015-01-01
@@ -176,7 +199,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
176
199
  end
177
200
 
178
201
  def test_record_attributes
179
- GrnMini::Hash.tmpdb do |hash|
202
+ GrnMini::tmpdb do
203
+ hash = GrnMini::Hash.new
204
+
180
205
  hash["a"] = {text:"aaaa", int: 1}
181
206
  hash["b"] = {text:"bbbb", int: 2}
182
207
  hash["c"] = {text:"cccc", int: 3}
@@ -188,7 +213,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
188
213
  end
189
214
 
190
215
  def test_assign_long_text_to_short_text
191
- GrnMini::Hash.tmpdb do |hash|
216
+ GrnMini::tmpdb do
217
+ hash = GrnMini::Hash.new
218
+
192
219
  hash["a"] = {filename:"a.txt"}
193
220
  hash["b"] = {filename:"a"*4095 + ".txt" } # Over 4095 byte (ShortText limit)
194
221
 
@@ -198,7 +225,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
198
225
  end
199
226
 
200
227
  def test_grn_object
201
- GrnMini::Hash.tmpdb do |hash|
228
+ GrnMini::tmpdb do
229
+ hash = GrnMini::Hash.new
230
+
202
231
  hash["a"] = {text: "aaaa", filename:"a.txt", int: 1, float: 1.5, time: Time.at(2001)}
203
232
 
204
233
  raw = hash.grn
@@ -221,7 +250,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
221
250
  end
222
251
 
223
252
  def test_sort
224
- GrnMini::Hash.tmpdb do |hash|
253
+ GrnMini::tmpdb do
254
+ hash = GrnMini::Hash.new
255
+
225
256
  hash["a"] = {name:"Tanaka", age: 11, height: 162.5}
226
257
  hash["b"] = {name:"Suzuki", age: 31, height: 170.0}
227
258
  hash["c"] = {name:"Hayashi", age: 21, height: 175.4}
@@ -245,7 +276,9 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
245
276
  end
246
277
 
247
278
  def test_group_from_hash
248
- GrnMini::Hash.tmpdb do |hash|
279
+ GrnMini::tmpdb do
280
+ hash = GrnMini::Hash.new
281
+
249
282
  hash["a"] = {text:"aaaa.txt", suffix:"txt", type:1}
250
283
  hash["b"] = {text:"aaaa.doc", suffix:"doc", type:2}
251
284
  hash["c"] = {text:"aabb.txt", suffix:"txt", type:2}
@@ -257,4 +290,90 @@ class TestGrnMiniHash < MiniTest::Unit::TestCase
257
290
  assert_equal ["doc", 1], [groups[1].key, groups[1].n_sub_records]
258
291
  end
259
292
  end
293
+
294
+ def test_select_table_element
295
+ GrnMini::tmpdb do
296
+ links = GrnMini::Hash.new("Links")
297
+ links.setup_columns(next: links)
298
+
299
+ links["aaa"] = {}
300
+ links["bbb"] = {}
301
+ links["ccc"] = {}
302
+
303
+ links["aaa"].next = links["bbb"]
304
+ links["bbb"].next = links["ccc"]
305
+ links["ccc"].next = links["aaa"]
306
+
307
+ assert_equal links["bbb"], links["aaa"].next
308
+
309
+ assert_equal links["ccc"], links.select("next: aaa").first.key
310
+ end
311
+ end
312
+
313
+ def test_nodes_table
314
+ GrnMini::tmpdb do
315
+ nodes = GrnMini::Hash.new("Nodes")
316
+ nodes.setup_columns(childs: [nodes], numbers: [0])
317
+
318
+ nodes["aaa"] = {}
319
+ nodes["bbb"] = {}
320
+ nodes["ccc"] = {}
321
+ nodes["ddd"] = {}
322
+ nodes["eee"] = {}
323
+
324
+ nodes["aaa"].childs = ["bbb", "ccc"]
325
+ # nodes["bbb"].childs = nodes["bbb"].childs + [nodes["ddd"]]
326
+ nodes["bbb"].childs += [nodes["ddd"]]
327
+ nodes["bbb"].childs += [nodes["eee"]]
328
+
329
+ assert_equal 2, nodes["aaa"].childs.size
330
+ assert_equal 2, nodes["bbb"].childs.size
331
+
332
+ assert_equal nodes["aaa"], nodes.select("childs: bbb").first.key
333
+ assert_equal 0, nodes.select("childs: aaa").size
334
+ end
335
+ end
336
+
337
+ def test_users_and_articles
338
+ GrnMini::tmpdb do
339
+ users = GrnMini::Hash.new("Users")
340
+ articles = GrnMini::Hash.new("Articles")
341
+
342
+ users.setup_columns(name: "", favorites: [articles])
343
+ articles.setup_columns(author: users, text: "")
344
+
345
+ users["aaa"] = {name: "Mr.A"}
346
+ users["bbb"] = {name: "Mr.B"}
347
+ users["ccc"] = {name: "Mr.C"}
348
+
349
+ articles["aaa:1"] = {author: "aaa", text: "111"}
350
+ articles["aaa:2"] = {author: "aaa", text: "222"}
351
+ articles["aaa:3"] = {author: "aaa", text: "333"}
352
+ articles["bbb:1"] = {author: "bbb", text: "111"}
353
+ articles["bbb:2"] = {author: "bbb", text: "222"}
354
+ articles["ccc:1"] = {author: "ccc", text: "111"}
355
+
356
+ users["aaa"].favorites = ["aaa:1", "bbb:2"]
357
+ users["bbb"].favorites = ["aaa:2"]
358
+ users["ccc"].favorites = ["aaa:1", "bbb:1", "ccc:1"]
359
+
360
+ assert_equal ["aaa", "ccc"], select_keys(users) { |record| record.favorites == "aaa:1" }
361
+ assert_equal ["bbb"], select_keys(users) { |record| record.favorites == "aaa:2" }
362
+ assert_equal [], select_keys(users) { |record| record.favorites == "aaa:3" }
363
+
364
+ assert_equal ["aaa", "ccc"], select_keys(users) { |record| record.favorites.text =~ "111" }
365
+ assert_equal ["aaa", "bbb"], select_keys(users) { |record| record.favorites.text =~ "222" }
366
+ assert_equal [], select_keys(users) { |record| record.favorites.text =~ "333" }
367
+
368
+ # assert_equal ["aaa", "ccc"], select_keys(users) { |record| record.favorites.text == "111" } # TODO ==だと動かない
369
+ # assert_equal ["aaa", "ccc"], select_keys(users) { |record| record.favorites.author == "bbb" } # TODO 正しく動かない
370
+ end
371
+ end
372
+
373
+ def select_keys(table)
374
+ table.select { |record|
375
+ yield record
376
+ }.map { |record| record._key }.sort
377
+ end
378
+
260
379
  end
@@ -0,0 +1,67 @@
1
+ require 'minitest_helper'
2
+
3
+ class TestMicroBlog < MiniTest::Unit::TestCase
4
+ def test_micro_blog
5
+ GrnMini::tmpdb do
6
+ engine = MicroBlog.new
7
+
8
+ # Add user
9
+ engine.add_user("aaa", "Mr. A", "Hello.")
10
+ engine.add_user("bbb", "Mr. B", "Good Afternoon.")
11
+ engine.add_user("ccc", "Mr. C", "Hi.")
12
+
13
+ # Follow
14
+ engine.follow("bbb", "aaa")
15
+ engine.follow("ccc", "aaa")
16
+ engine.follow("ccc", "bbb")
17
+
18
+ users = engine.users
19
+ assert_equal 0, users["aaa"].follower.size
20
+ assert_equal 1, users["bbb"].follower.size
21
+ assert_equal 2, users["ccc"].follower.size
22
+
23
+ # Followee
24
+ assert_equal 2, engine.followee("aaa").size
25
+ assert_equal 1, engine.followee("bbb").size
26
+ assert_equal 0, engine.followee("ccc").size
27
+ end
28
+ end
29
+
30
+ class MicroBlog
31
+ attr_reader :users
32
+ attr_reader :comments
33
+ attr_reader :hash_tags
34
+
35
+ def initialize
36
+ @users = GrnMini::Hash.new("Users")
37
+ @comments = GrnMini::Hash.new("Comments")
38
+ @hash_tags = GrnMini::Hash.new("HashTags")
39
+
40
+ @users.setup_columns(name: "User Name",
41
+ follower: [users],
42
+ favorites: [comments],
43
+ description: ""
44
+ )
45
+
46
+ @comments.setup_columns(comment: "",
47
+ last_modified: Time.new,
48
+ replied_to: [comments],
49
+ replied_users: [users],
50
+ hash_tags: [hash_tags],
51
+ posted_by: users
52
+ )
53
+ end
54
+
55
+ def add_user(id, name, description)
56
+ @users[id] = {name: name, description: description }
57
+ end
58
+
59
+ def follow(user_id, follow_id)
60
+ @users[user_id].follower += [@users[follow_id]]
61
+ end
62
+
63
+ def followee(user_id)
64
+ @users.select("follower:#{user_id}")
65
+ end
66
+ end
67
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grn_mini
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ongaeshi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-09 00:00:00.000000000 Z
11
+ date: 2014-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -79,6 +79,7 @@ files:
79
79
  - .gitignore
80
80
  - .travis.yml
81
81
  - Gemfile
82
+ - HISTORY.md
82
83
  - LICENSE.txt
83
84
  - README.md
84
85
  - Rakefile
@@ -86,13 +87,14 @@ files:
86
87
  - lib/grn_mini.rb
87
88
  - lib/grn_mini/array.rb
88
89
  - lib/grn_mini/hash.rb
90
+ - lib/grn_mini/table.rb
89
91
  - lib/grn_mini/util.rb
90
92
  - lib/grn_mini/version.rb
91
- - sample/mini-directory-search.rb
92
93
  - test/minitest_helper.rb
93
94
  - test/test_grn_mini.rb
94
95
  - test/test_grn_mini_array.rb
95
96
  - test/test_grn_mini_hash.rb
97
+ - test/test_micro_blog.rb
96
98
  homepage: ''
97
99
  licenses:
98
100
  - MIT
@@ -122,3 +124,4 @@ test_files:
122
124
  - test/test_grn_mini.rb
123
125
  - test/test_grn_mini_array.rb
124
126
  - test/test_grn_mini_hash.rb
127
+ - test/test_micro_blog.rb
@@ -1,153 +0,0 @@
1
- require 'grn_mini'
2
- require 'find'
3
- require 'kconv'
4
- require 'sinatra'
5
- require "sinatra/reloader" if ENV['SINATRA_RELOADER']
6
-
7
- module Input
8
- module_function
9
-
10
- def from_dir(array, dir = ".")
11
- index = 1
12
- puts "Create database .."
13
- Find.find(File.expand_path(dir)) do |filename|
14
- Find.prune if ignore_dir?(filename)
15
-
16
- if File.file? filename
17
- next if ignore_file?(filename)
18
- array << {filename: filename, text: read_file(filename), timestamp: File.stat(filename).mtime, suffix: File.extname(filename).sub('.', "")}
19
- index += 1
20
- end
21
- end
22
- puts "Input complete : #{array.size} files"
23
- end
24
-
25
- def read_file(filename)
26
- text = File.read(filename)
27
- Kconv.kconv(text, Kconv::UTF8).gsub("\r\n", "\n")
28
- end
29
-
30
- def ignore_dir?(filename)
31
- basename = File.basename(filename)
32
- /(\A\.svn\Z)|(\A\.git\Z)|(\ACVS\Z)/.match(basename)
33
- end
34
-
35
- def ignore_file?(filename)
36
- (s = File.read(filename, 1024)) && s.index("\x00")
37
- end
38
- end
39
-
40
- class Search
41
- def initialize(array, params)
42
- @array = array
43
- @params = params
44
- @page = @params[:page] ? @params[:page].to_i : 1
45
- end
46
-
47
- def has_query?
48
- @params[:query] && !@params[:query].empty?
49
- end
50
-
51
- def parse
52
- unless has_query?
53
- @header = "<span>#{@array.size} files.</span>"
54
- @content = ""
55
- @pagination = ""
56
- else
57
- results = @array.select(@params[:query])
58
-
59
- page_entries = results.paginate([["_score", :desc]], :page => @page, :size => 20)
60
- snippet = GrnMini::Util::html_snippet_from_selection_results(results, "<strong style=\"background-color: #FFEE55\">", "</strong>")
61
- elements = []
62
-
63
- page_entries.each do |record|
64
- element = "<hr>\n<a href=\"/#{record.value.key.id}\">#{record.filename}</a>\n"
65
-
66
- snippet.execute(record.text).each do |segment|
67
- element += "<pre style=\"border:1px solid #bbb;\">#{segment}</pre>\n"
68
- end
69
-
70
- elements << element
71
- end
72
-
73
- @header = "<span>#{page_entries.n_records} hit. (#{page_entries.start_offset} - #{page_entries.end_offset})</span>"
74
- @content = elements.join("\n")
75
-
76
- if page_entries.n_pages > 1
77
- @pagination += page_link(@page - 1, "&lt;-") + "&nbsp;" if @page > 1
78
-
79
- @pagination += page_range(page_entries).map {|v|
80
- if (v == @page)
81
- "<strong>#{v.to_s}</strong>"
82
- else
83
- page_link(v, v.to_s)
84
- end
85
- }.join("&nbsp;")
86
-
87
- @pagination += "&nbsp;" + page_link(@page + 1, "-&gt;") if @page < page_entries.n_pages
88
- end
89
- end
90
- end
91
-
92
- def page_range(page_entries)
93
- first_diff = [5 - (@page - 1), 0].max
94
- last_diff = [5 - (page_entries.n_pages - @page), 0].max
95
- [@page - 5 - last_diff, 1].max .. [@page + 5 + first_diff, page_entries.n_pages].min
96
- end
97
-
98
- def page_link(page, msg)
99
- "<a href=\"/?query=#{@params[:query]}&page=#{page}\">#{msg}</a>"
100
- end
101
-
102
- def html
103
- <<EOF
104
- #{@header}
105
- <div class="form">
106
- <form method="post" action="/search">
107
- <input type="text" style="width: 419px;" name="query" value="#{@params[:query]}">
108
- <input type="submit" value="Search">
109
- </form>
110
- </div>
111
- <div class="content">
112
- #{@content}
113
- </div>
114
- <div class="pagination">
115
- #{@pagination}
116
- </div>
117
- EOF
118
- end
119
- end
120
-
121
- ### main ###
122
- configure do
123
- $array = GrnMini::Array.new("mini-directory-search.db")
124
- Input.from_dir($array) if $array.empty?
125
- end
126
-
127
- get '/' do
128
- search = Search.new($array, params)
129
- search.parse
130
- search.html
131
- end
132
-
133
- get '/:id' do
134
- record = $array[params[:id].to_i]
135
-
136
- <<EOF
137
- <span>#{record.filename} (#{record.timestamp})</span>
138
- <div class="form">
139
- <form method="post" action="/search">
140
- <input type="text" style="width: 419px;" name="query" value="#{@params[:query]}">
141
- <input type="submit" value="Search">
142
- </form>
143
- </div>
144
- <div class="content">
145
- <hr>
146
- <pre>#{CGI.escapeHTML(record.text)}</pre>
147
- </div>
148
- EOF
149
- end
150
-
151
- post '/search' do
152
- redirect "/?query=#{escape(params[:query])}"
153
- end