ion 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/README.md +280 -0
- data/Rakefile +13 -0
- data/lib/ion.rb +84 -0
- data/lib/ion/config.rb +16 -0
- data/lib/ion/entity.rb +48 -0
- data/lib/ion/helpers.rb +11 -0
- data/lib/ion/index.rb +56 -0
- data/lib/ion/indices.rb +18 -0
- data/lib/ion/indices/metaphone.rb +7 -0
- data/lib/ion/indices/number.rb +31 -0
- data/lib/ion/indices/sort.rb +41 -0
- data/lib/ion/indices/text.rb +41 -0
- data/lib/ion/options.rb +46 -0
- data/lib/ion/scope.rb +163 -0
- data/lib/ion/search.rb +83 -0
- data/lib/ion/stringer.rb +17 -0
- data/test/irb_helpers.rb +9 -0
- data/test/p_helper.rb +31 -0
- data/test/redis_debug.rb +8 -0
- data/test/test_helper.rb +81 -0
- data/test/unit/boost_test.rb +28 -0
- data/test/unit/config_test.rb +25 -0
- data/test/unit/hash_test.rb +48 -0
- data/test/unit/ion_test.rb +112 -0
- data/test/unit/metaphone_test.rb +37 -0
- data/test/unit/number_test.rb +46 -0
- data/test/unit/options_test.rb +18 -0
- data/test/unit/range_test.rb +76 -0
- data/test/unit/score_test.rb +43 -0
- data/test/unit/sort_test.rb +36 -0
- data/test/unit/subscope_test.rb +44 -0
- data/test/unit/ttl_test.rb +40 -0
- data/test/unit/update_test.rb +42 -0
- metadata +121 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
class IT::Options < Ohm::Model
|
4
|
+
include Ion::Entity
|
5
|
+
include Ohm::Callbacks
|
6
|
+
|
7
|
+
attribute :text
|
8
|
+
end
|
9
|
+
|
10
|
+
class OptionsTest < Test::Unit::TestCase
|
11
|
+
test "foo" do
|
12
|
+
assert_raise(Ion::InvalidIndexType) do
|
13
|
+
IT::Options.ion {
|
14
|
+
field :footype, :text
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
class RangeTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
# Fake entries that should NOT be returned
|
6
|
+
5.times { Album.create title: lorem, body: '' }
|
7
|
+
|
8
|
+
@items = {
|
9
|
+
:a => Album.create(title: "X Morning Scifi"),
|
10
|
+
:b => Album.create(title: "X Intensify", body: 'Special Edition'),
|
11
|
+
:c => Album.create(title: "X BT Emotional Technology", body: 'Special Edition'),
|
12
|
+
:d => Album.create(title: "X BT Movement in Still Life"),
|
13
|
+
:e => Album.create(title: "X Involver"),
|
14
|
+
:f => Album.create(title: "X Bullet"),
|
15
|
+
:g => Album.create(title: "X Fear of a Silver Planet"),
|
16
|
+
:h => Album.create(title: "X Renaissance: Everybody")
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
test "ranges" do
|
21
|
+
search = Album.ion.search { text :title, 'x' }
|
22
|
+
ids = search.ids
|
23
|
+
|
24
|
+
search.range from: 2, limit: 1
|
25
|
+
|
26
|
+
assert_equal (1..1), search.range
|
27
|
+
assert_equal ids[1..1], search.ids
|
28
|
+
|
29
|
+
search.range from: 4, to: 4
|
30
|
+
assert_equal (3..3), search.range
|
31
|
+
assert_equal ids[3..3], search.ids
|
32
|
+
|
33
|
+
search.range from: 1, to: 3
|
34
|
+
assert_equal (0..2), search.range
|
35
|
+
assert_equal ids[0..2], search.ids
|
36
|
+
|
37
|
+
search.range (3..4)
|
38
|
+
assert_equal (3..4), search.range
|
39
|
+
assert_equal ids[3..4], search.ids
|
40
|
+
|
41
|
+
search.range (3..-1)
|
42
|
+
assert_equal (3..-1), search.range
|
43
|
+
assert_equal ids[3..-1], search.ids
|
44
|
+
|
45
|
+
search.range (3..-3)
|
46
|
+
assert_equal (3..-3), search.range
|
47
|
+
assert_equal ids[3..-3], search.ids
|
48
|
+
|
49
|
+
search.range (3...4)
|
50
|
+
assert_equal (3...4), search.range
|
51
|
+
assert_equal ids[3...4], search.ids
|
52
|
+
|
53
|
+
search.range (3...-1)
|
54
|
+
assert_equal (3...-1), search.range
|
55
|
+
assert_equal ids[3...-1], search.ids
|
56
|
+
|
57
|
+
search.range :all
|
58
|
+
assert_equal (0..-1), search.range
|
59
|
+
assert_equal ids, search.ids
|
60
|
+
end
|
61
|
+
|
62
|
+
test "iterating through ranges" do
|
63
|
+
search = Album.ion.search { text :title, 'x' }
|
64
|
+
ids = search.ids
|
65
|
+
search.range from: 2, limit: 4
|
66
|
+
|
67
|
+
assert_equal 4, search.ids.size
|
68
|
+
assert_equal 8, search.size
|
69
|
+
|
70
|
+
injected = search.inject(0) { |i, _| i += 1 }
|
71
|
+
assert_equal 4, injected
|
72
|
+
|
73
|
+
mapped = search.map { 1 }
|
74
|
+
assert_equal [1,1,1,1], mapped
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
class ScoreTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
# Fake entries that should NOT be returned
|
6
|
+
5.times { Album.create title: lorem, body: '' }
|
7
|
+
|
8
|
+
@items = {
|
9
|
+
:a => Album.create(title: "Secher glite"),
|
10
|
+
:b => Album.create(title: "Shebboleth mordor"),
|
11
|
+
:c => Album.create(title: "Rexan ruffush"),
|
12
|
+
:d => Album.create(title: "Parctris leroux")
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
test "scores" do
|
17
|
+
search = Album.ion.search {
|
18
|
+
score(2.5) {
|
19
|
+
text :title, "secher"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
assert_ids %w(a), for: search
|
24
|
+
|
25
|
+
@scores = scores_for search
|
26
|
+
assert_score a: 2.5
|
27
|
+
end
|
28
|
+
|
29
|
+
test "nested scores" do
|
30
|
+
search = Album.ion.search {
|
31
|
+
score(2.5) {
|
32
|
+
score(2.0) {
|
33
|
+
text :title, "secher"
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
assert_ids %w(a), for: search
|
39
|
+
|
40
|
+
@scores = scores_for search
|
41
|
+
assert_score a: 5.0
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
class SortTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
# Fake entries that should NOT be returned
|
6
|
+
5.times { Album.create title: lorem, body: '' }
|
7
|
+
|
8
|
+
@items = {
|
9
|
+
:r1 => Album.create(title: "Eurostile x"),
|
10
|
+
:r2 => Album.create(title: "Garamond x"),
|
11
|
+
:r3 => Album.create(title: "Didot x"),
|
12
|
+
:r4 => Album.create(title: "Caslon x"),
|
13
|
+
:r5 => Album.create(title: "Avenir x"),
|
14
|
+
:r6 => Album.create(title: "The Bodoni x"),
|
15
|
+
:r7 => Album.create(title: "Helvetica x"),
|
16
|
+
:r8 => Album.create(title: "Futura x")
|
17
|
+
}
|
18
|
+
|
19
|
+
@search = Album.ion.search { text :title, 'x' }
|
20
|
+
@search.sort_by :title
|
21
|
+
end
|
22
|
+
|
23
|
+
test "sort" do
|
24
|
+
assert_ids %w(r5 r6 r4 r3 r1 r8 r2 r7), for: @search, ordered: true
|
25
|
+
end
|
26
|
+
|
27
|
+
test "range 1" do
|
28
|
+
@search.range from: 1, limit: 4
|
29
|
+
assert_ids %w(r5 r6 r4 r3), for: @search, ordered: true
|
30
|
+
end
|
31
|
+
|
32
|
+
test "range 2" do
|
33
|
+
@search.range from: 2, limit: 4
|
34
|
+
assert_ids %w(r6 r4 r3 r1), for: @search, ordered: true
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
class SubscopeTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
# Fake entries that should NOT be returned
|
6
|
+
5.times { Album.create title: lorem, body: '' }
|
7
|
+
|
8
|
+
@items = {
|
9
|
+
:a => Album.create(title: "Secher glite"),
|
10
|
+
:b => Album.create(title: "Shebboleth mordor"),
|
11
|
+
:c => Album.create(title: "Rexan ruffush"),
|
12
|
+
:d => Album.create(title: "Parctris leroux")
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
test "nested 1" do
|
17
|
+
search = Album.ion.search {
|
18
|
+
any_of {
|
19
|
+
text :title, "secher"
|
20
|
+
text :title, "mordor"
|
21
|
+
all_of {
|
22
|
+
text :title, "rexan"
|
23
|
+
text :title, "ruffush"
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
assert_ids %w(a b c), for: search
|
29
|
+
end
|
30
|
+
|
31
|
+
test "nested 2" do
|
32
|
+
search = Album.ion.search {
|
33
|
+
any_of {
|
34
|
+
text :title, "shebboleth"
|
35
|
+
all_of {
|
36
|
+
text :title, "rexan"
|
37
|
+
text :title, "ruffush"
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
assert_ids %w(b c), for: search
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
class TtlTest < Test::Unit::TestCase
|
4
|
+
test "key TTL test" do
|
5
|
+
Album.create title: "Vloop", body: "Secher Betrib"
|
6
|
+
|
7
|
+
old_keys = redis.keys('Ion:*').reject { |s| s['~'] }
|
8
|
+
|
9
|
+
# This should make a bunch of temp keys
|
10
|
+
search = Album.ion.search {
|
11
|
+
text :title, "Vloop"
|
12
|
+
text :body, "Secher betrib"
|
13
|
+
any_of {
|
14
|
+
text :body, "betrib"
|
15
|
+
text :body, "betrib"
|
16
|
+
any_of {
|
17
|
+
text :body, "betrib"
|
18
|
+
text :body, "betrib"
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
search.ids
|
24
|
+
|
25
|
+
# Ensure all temp keys will die eventually
|
26
|
+
keys = redis.keys('Ion:~:*')
|
27
|
+
keys.each { |key|
|
28
|
+
ttl = redis.ttl(key)
|
29
|
+
assert ttl >= 0
|
30
|
+
}
|
31
|
+
|
32
|
+
new_keys = redis.keys('Ion:*').reject { |s| s['~'] }
|
33
|
+
|
34
|
+
# Ensure that no keys died
|
35
|
+
assert_equal old_keys.sort, new_keys.sort
|
36
|
+
|
37
|
+
# Ensure they're all alive
|
38
|
+
new_keys.each { |key| assert_equal -1, redis.ttl(key) }
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
class UpdateTest < Test::Unit::TestCase
|
4
|
+
setup do
|
5
|
+
# Fake entries that should NOT be returned
|
6
|
+
5.times { Album.create title: lorem, body: '' }
|
7
|
+
end
|
8
|
+
|
9
|
+
test "Deleting records" do
|
10
|
+
item = Album.create title: "Shobeh"
|
11
|
+
search = Album.ion.search { text :title, "Shobeh" }
|
12
|
+
id = item.id
|
13
|
+
|
14
|
+
# Search should see it
|
15
|
+
assert_equal [id], search.ids
|
16
|
+
|
17
|
+
item.delete
|
18
|
+
assert Album[id].nil?
|
19
|
+
|
20
|
+
search = Album.ion.search { text :title, "Shobeh" }
|
21
|
+
assert_equal [], search.ids
|
22
|
+
end
|
23
|
+
|
24
|
+
test "Editing records" do
|
25
|
+
item = Album.create title: "Heshela"
|
26
|
+
search = Album.ion.search { text :title, "Heshela" }
|
27
|
+
|
28
|
+
# Search should see it
|
29
|
+
assert_equal [item.id], search.ids
|
30
|
+
|
31
|
+
# Edit
|
32
|
+
item.title = "Mathroux"
|
33
|
+
item.save
|
34
|
+
|
35
|
+
# Now search should not see it
|
36
|
+
search = Album.ion.search { text :title, "Heshela" }
|
37
|
+
assert_equal [], search.ids
|
38
|
+
|
39
|
+
search = Album.ion.search { text :title, "mathroux" }
|
40
|
+
assert_equal [item.id], search.ids
|
41
|
+
end
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ion
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rico Sta. Cruz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-02-13 00:00:00 +08:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: nest
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "1.0"
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: redis
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ~>
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "2.1"
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: text
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.2.0
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id003
|
49
|
+
description: Ion is a library that lets you index your records and search them with simple or complex queries.
|
50
|
+
email:
|
51
|
+
- rico@sinefunc.com
|
52
|
+
executables: []
|
53
|
+
|
54
|
+
extensions: []
|
55
|
+
|
56
|
+
extra_rdoc_files: []
|
57
|
+
|
58
|
+
files:
|
59
|
+
- lib/ion/config.rb
|
60
|
+
- lib/ion/entity.rb
|
61
|
+
- lib/ion/helpers.rb
|
62
|
+
- lib/ion/index.rb
|
63
|
+
- lib/ion/indices/metaphone.rb
|
64
|
+
- lib/ion/indices/number.rb
|
65
|
+
- lib/ion/indices/sort.rb
|
66
|
+
- lib/ion/indices/text.rb
|
67
|
+
- lib/ion/indices.rb
|
68
|
+
- lib/ion/options.rb
|
69
|
+
- lib/ion/scope.rb
|
70
|
+
- lib/ion/search.rb
|
71
|
+
- lib/ion/stringer.rb
|
72
|
+
- lib/ion.rb
|
73
|
+
- README.md
|
74
|
+
- Rakefile
|
75
|
+
- test/irb_helpers.rb
|
76
|
+
- test/p_helper.rb
|
77
|
+
- test/redis_debug.rb
|
78
|
+
- test/test_helper.rb
|
79
|
+
- test/unit/boost_test.rb
|
80
|
+
- test/unit/config_test.rb
|
81
|
+
- test/unit/hash_test.rb
|
82
|
+
- test/unit/ion_test.rb
|
83
|
+
- test/unit/metaphone_test.rb
|
84
|
+
- test/unit/number_test.rb
|
85
|
+
- test/unit/options_test.rb
|
86
|
+
- test/unit/range_test.rb
|
87
|
+
- test/unit/score_test.rb
|
88
|
+
- test/unit/sort_test.rb
|
89
|
+
- test/unit/subscope_test.rb
|
90
|
+
- test/unit/ttl_test.rb
|
91
|
+
- test/unit/update_test.rb
|
92
|
+
has_rdoc: true
|
93
|
+
homepage: http://github.com/rstacruz/ion
|
94
|
+
licenses: []
|
95
|
+
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: "0"
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: "0"
|
113
|
+
requirements: []
|
114
|
+
|
115
|
+
rubyforge_project:
|
116
|
+
rubygems_version: 1.5.0
|
117
|
+
signing_key:
|
118
|
+
specification_version: 3
|
119
|
+
summary: Simple search engine powered by Redis.
|
120
|
+
test_files: []
|
121
|
+
|