redis-autosuggest 0.0.1 → 0.1.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.
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Redis::Autosuggest
2
2
 
3
- TODO: Write a gem description
3
+ Provides autocompletions through Redis, with the ability to rank
4
+ results and integrate with Rails
4
5
 
5
6
  ## Installation
6
7
 
@@ -18,7 +19,56 @@ Or install it yourself as:
18
19
 
19
20
  ## Usage
20
21
 
21
- TODO: Write usage instructions here
22
+ By default Autosuggest creates a new Redis client on db 0 at localhost:6379.
23
+
24
+ To change the server/port:
25
+ ```ruby
26
+ r = Redis.new(:host => "my_host", :port => my_port)
27
+ Redis::Autosuggest.redis = r
28
+ ```
29
+
30
+ To add items to be use for autocompletions:
31
+ ```ruby
32
+ Redis::Autosuggest.add("North By Northwest", "Northern Exposure")
33
+ ```
34
+
35
+ To check for autocompletions for an item:
36
+ ```ruby
37
+ Redis::Autosuggest.suggest("nor")
38
+ # => ["north by northwest", "northern exposure"]
39
+ ```
40
+ Autocompletions will be ordered their score value (descending).
41
+
42
+ Some other usage examples:
43
+ ```ruby
44
+ # Add items with initial scores
45
+ Redis::Autosuggest.suggest("North By Northwest", 9, Northern Exposure, 3)
46
+ # Increment an item's score
47
+ Redis::Autosuggest.suggest("North By Northwest", 1)
48
+ ```
49
+
50
+ ## Rails support
51
+
52
+ Autosuggest can also be integrated with Rails. Include it in a model:
53
+ ```ruby
54
+ class Movie < ActiveRecord::Base
55
+ include Redis::Autosuggest
56
+
57
+ attr_accessible :movie_title
58
+ autosuggest :movie_title
59
+ end
60
+ ```
61
+
62
+ For first time usage, seed the Redis db with the autosuggest sources:
63
+ ```ruby
64
+ Redis::Autosuggest.init_rails_sources
65
+ ```
66
+
67
+ You can optionally specify a numeric field to be used as the initial score for an item
68
+ when it is added:
69
+ ```ruby
70
+ autosuggest :movie_title, :rank_by => imdb_rating
71
+ ```
22
72
 
23
73
  ## Contributing
24
74
 
@@ -1,5 +1,11 @@
1
1
  require 'redis'
2
2
  require 'redis-namespace'
3
3
  require 'redis/autosuggest'
4
- require 'redis/autosuggest/version'
5
4
  require 'redis/autosuggest/config'
5
+ require 'redis/autosuggest/file'
6
+ require 'redis/autosuggest/init'
7
+ require 'redis/autosuggest/version'
8
+
9
+ if defined?(Rails)
10
+ require 'redis/autosuggest/rails'
11
+ end
@@ -12,7 +12,7 @@ class Redis
12
12
  add_item(i.downcase)
13
13
  end
14
14
  end
15
-
15
+
16
16
  # Add item(s) along with their scores.
17
17
  # add_with_score("item1", 4, "item2", 1, "item3", 0)
18
18
  def add_with_score(*fields)
@@ -55,6 +55,11 @@ class Redis
55
55
  top_ids.empty? ? [] : @db.hmget(@items, top_ids)
56
56
  end
57
57
 
58
+ # Get the score of an item
59
+ def get_score(item)
60
+ @substrings.zscore(item.downcase, get_id(item.downcase))
61
+ end
62
+
58
63
  private
59
64
  def add_item(item, score=0)
60
65
  id = self.db.hlen(self.items)
@@ -23,15 +23,19 @@ class Redis
23
23
 
24
24
  # Key to a sorted set holding all id of items in the autosuggest database sorted
25
25
  # by their score
26
- @leaderboard = "leaderboard"
26
+ @leaderboard = "lead"
27
27
 
28
28
  # Leaderboard off by default
29
29
  @use_leaderboard = false
30
30
 
31
+ # Sources to be used for Autocomplete in rails.
32
+ # Example: { Movie => :movie_title }
33
+ @rails_sources = {}
34
+
31
35
  class << self
32
36
  attr_reader :redis
33
37
  attr_accessor :db, :items, :substrings, :max_per_substring, :max_results,
34
- :leaderboard, :use_leaderboard
38
+ :leaderboard, :use_leaderboard, :rails_sources
35
39
 
36
40
  def redis=(redis)
37
41
  @redis = redis
@@ -0,0 +1,23 @@
1
+ class Redis
2
+ module Autosuggest
3
+
4
+ class << self
5
+
6
+ # Add items to the autosuggest database from a file.
7
+ # Each line be a string representing the item
8
+ def add_from_file(file)
9
+ add(*(File.open(file, "r").map { |l| l.strip }))
10
+ end
11
+
12
+ # Add items and their to the autosuggest database from a file.
13
+ # Each line be a string representing the item followed by its score
14
+ # Example:
15
+ # item1 0.4
16
+ # item2 2.1
17
+ # item3 5.2
18
+ def add_with_score_from_file(file)
19
+ add_with_score(*(File.open(file, "r").map { |l| l.split(" ")}.flatten))
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ class Redis
2
+ module Autosuggest
3
+
4
+ class << self
5
+
6
+ def init_rails_sources
7
+ self.rails_sources.each_key do |r|
8
+ r.all.each do |record|
9
+ record.add_to_autosuggest
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+
@@ -0,0 +1,49 @@
1
+ class Redis
2
+ module Autosuggest
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+
7
+ def autosuggest(column, options={})
8
+ hash = Redis::Autosuggest.rails_sources[self]
9
+ if hash.nil?
10
+ Redis::Autosuggest.rails_sources[self] = { column => options }
11
+ else
12
+ hash[column] = options
13
+ end
14
+
15
+ # hook onto rails callbacks to update autosuggest db if a source is modified
16
+ class_eval <<-HERE
17
+ after_create :add_to_autosuggest
18
+ def add_to_autosuggest
19
+ Redis::Autosuggest.rails_sources[self.class].each do |column, options|
20
+ score = self.send(options[:rank_by]) if !options[:rank_by].nil?
21
+ score ||= 0
22
+ Redis::Autosuggest.add_with_score(self.send(column), score)
23
+ end
24
+ end
25
+
26
+ after_update :check_if_changed
27
+ def check_if_changed
28
+ Redis::Autosuggest.rails_sources[self.class].each_key do |column|
29
+ next if !self.send("#{column}_changed?")
30
+ old_item = self.send("#{column}_was")
31
+ score = Redis::Autosuggest.get_score(old_item)
32
+ Redis::Autosuggest.remove(old_item)
33
+ Redis::Autosuggest.add_with_score(self.send(column), score)
34
+ end
35
+ end
36
+
37
+ before_destroy :remove_from_autosuggest
38
+ def remove_from_autosuggest
39
+ Redis::Autosuggest.rails_sources[self.class].each_key do |column|
40
+ Redis::Autosuggest.remove(self.send(column))
41
+ end
42
+ end
43
+ HERE
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+
@@ -1,5 +1,5 @@
1
1
  class Redis
2
2
  module Autosuggest
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -21,6 +21,5 @@ Gem::Specification.new do |gem|
21
21
  gem.add_dependency("redis", "~> 3.0.1")
22
22
  gem.add_dependency("redis-namespace", "~> 1.2.1")
23
23
 
24
- gem.add_development_dependency("debugger", "~> 1.2.0")
25
24
  gem.add_development_dependency("minitest", "~> 3.5.0")
26
25
  end
@@ -1,18 +1,9 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class TestAutosuggest < MiniTest::Unit::TestCase
4
-
4
+
5
5
  def self.unused_db
6
- @unused_db ||= Redis.new(:db => db_picker)
7
- end
8
-
9
- # get an unused db so that we can safely clear all keys
10
- def self.db_picker
11
- redis = Redis.new
12
- (0..15).each do |i|
13
- redis.select(i)
14
- return i if redis.keys.empty?
15
- end
6
+ @unused_db ||= Redis.new(:db => TestHelper.db_picker)
16
7
  end
17
8
 
18
9
  def setup
@@ -109,5 +100,10 @@ class TestAutosuggest < MiniTest::Unit::TestCase
109
100
  Redis::Autosuggest.use_leaderboard = false
110
101
  end
111
102
 
103
+ def test_getting_an_items_score
104
+ Redis::Autosuggest.add_with_score(@str1, 3)
105
+ assert_equal 3, Redis::Autosuggest.get_score(@str1)
106
+ end
107
+
112
108
  MiniTest::Unit.after_tests { self.unused_db.flushdb }
113
109
  end
data/test/file_test.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'test_helper'
2
+
3
+ class TestFile < MiniTest::Unit::TestCase
4
+
5
+ def self.unused_db
6
+ @unused_db ||= Redis.new(:db => TestHelper.db_picker)
7
+ end
8
+
9
+ def setup
10
+ self.class.unused_db.flushdb
11
+ Redis::Autosuggest.redis = self.class.unused_db
12
+ @db = Redis::Autosuggest.db
13
+ @subs = Redis::Autosuggest.substrings
14
+ end
15
+
16
+ def test_adding_from_file
17
+ Redis::Autosuggest.add_from_file("test/text/example.txt")
18
+ assert @db.hgetall(Redis::Autosuggest.items).size == 3
19
+ assert @subs.keys.size == 10
20
+ end
21
+
22
+ def test_adding_with_score_from_file
23
+ Redis::Autosuggest.add_with_score_from_file("test/text/example_with_score.txt")
24
+ assert @db.hgetall(Redis::Autosuggest.items).size == 3
25
+ assert @subs.keys.size == 10
26
+ assert_equal 12, @subs.zscore("one", 0)
27
+ assert_equal 4, @subs.zscore("two", 1)
28
+ assert_equal 3, @subs.zscore("three", 2)
29
+ end
30
+
31
+ MiniTest::Unit.after_tests { self.unused_db.flushdb }
32
+ end
33
+
data/test/test_helper.rb CHANGED
@@ -4,3 +4,15 @@ require 'debugger'
4
4
  require 'redis'
5
5
  require 'redis-namespace'
6
6
  require 'redis-autosuggest'
7
+
8
+
9
+ class TestHelper
10
+ # get an unused db so that we can safely clear all keys
11
+ def self.db_picker
12
+ redis = Redis.new
13
+ (0..15).each do |i|
14
+ redis.select(i)
15
+ return i if redis.keys.empty?
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ one
2
+ two
3
+ three
@@ -0,0 +1,3 @@
1
+ one 12
2
+ two 4
3
+ three 3
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-autosuggest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -43,22 +43,6 @@ dependencies:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
45
  version: 1.2.1
46
- - !ruby/object:Gem::Dependency
47
- name: debugger
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ~>
52
- - !ruby/object:Gem::Version
53
- version: 1.2.0
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: 1.2.0
62
46
  - !ruby/object:Gem::Dependency
63
47
  name: minitest
64
48
  requirement: !ruby/object:Gem::Requirement
@@ -91,10 +75,16 @@ files:
91
75
  - lib/redis-autosuggest.rb
92
76
  - lib/redis/autosuggest.rb
93
77
  - lib/redis/autosuggest/config.rb
78
+ - lib/redis/autosuggest/file.rb
79
+ - lib/redis/autosuggest/init.rb
80
+ - lib/redis/autosuggest/rails.rb
94
81
  - lib/redis/autosuggest/version.rb
95
82
  - redis-autosuggest.gemspec
96
83
  - test/autosuggest_test.rb
84
+ - test/file_test.rb
97
85
  - test/test_helper.rb
86
+ - test/text/example.txt
87
+ - test/text/example_with_score.txt
98
88
  homepage: https://github.com/aphan/redis-autosuggest
99
89
  licenses: []
100
90
  post_install_message:
@@ -121,4 +111,7 @@ specification_version: 3
121
111
  summary: Suggestions/autocompletions with Redis and Ruby
122
112
  test_files:
123
113
  - test/autosuggest_test.rb
114
+ - test/file_test.rb
124
115
  - test/test_helper.rb
116
+ - test/text/example.txt
117
+ - test/text/example_with_score.txt