redis-autosuggest 0.1.0 → 0.2.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 +7 -22
- data/lib/redis-autosuggest.rb +2 -2
- data/lib/redis/autosuggest.rb +76 -30
- data/lib/redis/autosuggest/config.rb +18 -9
- data/lib/redis/autosuggest/rails/railtie.rb +10 -0
- data/lib/redis/autosuggest/rails/rake_tasks.rb +9 -0
- data/lib/redis/autosuggest/rails/sources.rb +100 -0
- data/lib/redis/autosuggest/version.rb +1 -1
- data/redis-autosuggest.gemspec +2 -2
- data/test/autosuggest_test.rb +12 -4
- data/test/file_test.rb +0 -1
- metadata +9 -8
- data/lib/redis/autosuggest/init.rb +0 -17
- data/lib/redis/autosuggest/rails.rb +0 -49
data/README.md
CHANGED
@@ -5,16 +5,6 @@ Provides autocompletions through Redis, with the ability to rank
|
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
8
|
-
Add this line to your application's Gemfile:
|
9
|
-
|
10
|
-
gem 'redis-autosuggest'
|
11
|
-
|
12
|
-
And then execute:
|
13
|
-
|
14
|
-
$ bundle
|
15
|
-
|
16
|
-
Or install it yourself as:
|
17
|
-
|
18
8
|
$ gem install redis-autosuggest
|
19
9
|
|
20
10
|
## Usage
|
@@ -42,9 +32,9 @@ Autocompletions will be ordered their score value (descending).
|
|
42
32
|
Some other usage examples:
|
43
33
|
```ruby
|
44
34
|
# Add items with initial scores
|
45
|
-
Redis::Autosuggest.
|
35
|
+
Redis::Autosuggest.add_with_score("North By Northwest", 9, Northern Exposure, 3)
|
46
36
|
# Increment an item's score
|
47
|
-
Redis::Autosuggest.
|
37
|
+
Redis::Autosuggest.increment("North By Northwest", 1)
|
48
38
|
```
|
49
39
|
|
50
40
|
## Rails support
|
@@ -61,19 +51,14 @@ end
|
|
61
51
|
|
62
52
|
For first time usage, seed the Redis db with the autosuggest sources:
|
63
53
|
```ruby
|
64
|
-
|
54
|
+
rake autosuggest:init
|
65
55
|
```
|
66
56
|
|
67
57
|
You can optionally specify a numeric field to be used as the initial score for an item
|
68
|
-
when it is added:
|
58
|
+
when it is added and a limit of how many items maximum to keep:
|
69
59
|
```ruby
|
70
|
-
autosuggest
|
60
|
+
autosuggest :movie_title, :rank_by => imdb_rating, limit => 10000
|
71
61
|
```
|
72
62
|
|
73
|
-
##
|
74
|
-
|
75
|
-
1. Fork it
|
76
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
77
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
78
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
79
|
-
5. Create new Pull Request
|
63
|
+
## Front-end portion
|
64
|
+
Jquery plugin for dropdown autocompletions for a from can be found [here](https://github.com/aphan/jquery-rtsuggest)
|
data/lib/redis-autosuggest.rb
CHANGED
@@ -3,9 +3,9 @@ require 'redis-namespace'
|
|
3
3
|
require 'redis/autosuggest'
|
4
4
|
require 'redis/autosuggest/config'
|
5
5
|
require 'redis/autosuggest/file'
|
6
|
-
require 'redis/autosuggest/init'
|
7
6
|
require 'redis/autosuggest/version'
|
8
7
|
|
9
8
|
if defined?(Rails)
|
10
|
-
require 'redis/autosuggest/rails'
|
9
|
+
require 'redis/autosuggest/rails/sources'
|
10
|
+
require 'redis/autosuggest/rails/railtie'
|
11
11
|
end
|
data/lib/redis/autosuggest.rb
CHANGED
@@ -4,48 +4,54 @@ class Redis
|
|
4
4
|
class << self
|
5
5
|
|
6
6
|
# Add item(s) to the pool of items to autosuggest from. Each item's initial
|
7
|
-
# rank is 0
|
7
|
+
# rank is 0. Returns true if all items added were new, false otherwise.
|
8
8
|
def add(*items)
|
9
|
-
|
10
|
-
items.each do |
|
11
|
-
|
12
|
-
add_item(
|
9
|
+
all_new_items = true
|
10
|
+
items.each do |item|
|
11
|
+
item = item.downcase
|
12
|
+
item_exists?(item) ? all_new_items = false : add_item(item)
|
13
13
|
end
|
14
|
+
all_new_items
|
14
15
|
end
|
15
16
|
|
16
|
-
# Add item(s) along with their scores.
|
17
|
+
# Add item(s) along with their initial scores.
|
18
|
+
# Returns true if all items added were new, false otherwise.
|
17
19
|
# add_with_score("item1", 4, "item2", 1, "item3", 0)
|
18
20
|
def add_with_score(*fields)
|
19
|
-
|
21
|
+
all_new_items = true
|
20
22
|
fields.each_slice(2) do |f|
|
21
|
-
|
22
|
-
|
23
|
+
f[0] = normalize(f[0])
|
24
|
+
item_exists?(f[0]) ? all_new_items = false : add_item(*f)
|
23
25
|
end
|
26
|
+
all_new_items
|
24
27
|
end
|
25
28
|
|
26
|
-
# Remove an item from the pool of items to autosuggest from
|
29
|
+
# Remove an item from the pool of items to autosuggest from.
|
30
|
+
# Returns true if an item was indeed removed, false otherwise.
|
27
31
|
def remove(item)
|
28
32
|
item = item.downcase
|
29
33
|
id = get_id(item)
|
30
|
-
return if id.nil?
|
34
|
+
return false if id.nil?
|
31
35
|
@db.hdel(@items, id)
|
36
|
+
@db.hdel(@itemids, item)
|
32
37
|
remove_substrings(item, id)
|
33
38
|
@redis.zrem(@leaderboard, id) if @use_leaderboard
|
39
|
+
return true
|
34
40
|
end
|
35
41
|
|
36
|
-
# Increment the score (by 1 by default) of an item.
|
37
|
-
# to decrement the score
|
38
|
-
def increment(item,
|
39
|
-
item = item
|
42
|
+
# Increment the score (by 1 by default) of an item.
|
43
|
+
# Pass in a negative value to decrement the score.
|
44
|
+
def increment(item, incr=1)
|
45
|
+
item = normalize(item)
|
40
46
|
id = get_id(item)
|
41
|
-
each_substring(item) { |sub| @substrings.zincrby(sub,
|
42
|
-
@db.zincrby(@leaderboard,
|
47
|
+
each_substring(item) { |sub| @substrings.zincrby(sub, incr, id) }
|
48
|
+
@db.zincrby(@leaderboard, incr, id) if @use_leaderboard
|
43
49
|
end
|
44
50
|
|
45
51
|
# Suggest items from the database that most closely match the queried string.
|
46
|
-
# Returns an array of suggestion items (an empty array if nothing found)
|
52
|
+
# Returns an array of suggestion items (an empty array if nothing found).
|
47
53
|
def suggest(str, results=@max_results)
|
48
|
-
suggestion_ids = @substrings.zrevrange(str
|
54
|
+
suggestion_ids = @substrings.zrevrange(normalize(str), 0, results - 1)
|
49
55
|
suggestion_ids.empty? ? [] : @db.hmget(@items, suggestion_ids)
|
50
56
|
end
|
51
57
|
|
@@ -57,15 +63,32 @@ class Redis
|
|
57
63
|
|
58
64
|
# Get the score of an item
|
59
65
|
def get_score(item)
|
60
|
-
|
66
|
+
item = normalize(item)
|
67
|
+
@substrings.zscore(item, get_id(item))
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns whether or not an item is already stored in the db
|
71
|
+
def item_exists?(item)
|
72
|
+
return !get_id(normalize(item)).nil?
|
73
|
+
end
|
74
|
+
|
75
|
+
# Get the id associated with an item in the db
|
76
|
+
def get_id(item)
|
77
|
+
return @db.hmget(@itemids, normalize(item)).first
|
61
78
|
end
|
62
79
|
|
63
80
|
private
|
81
|
+
|
82
|
+
def normalize(item)
|
83
|
+
return item.downcase.strip
|
84
|
+
end
|
85
|
+
|
64
86
|
def add_item(item, score=0)
|
65
|
-
id =
|
66
|
-
|
87
|
+
id = @db.hlen(@items)
|
88
|
+
@db.hset(@items, id, item)
|
89
|
+
@db.hset(@itemids, item, id)
|
67
90
|
add_substrings(item, score, id)
|
68
|
-
|
91
|
+
@db.zadd(@leaderboard, score, id) if @use_leaderboard
|
69
92
|
end
|
70
93
|
|
71
94
|
# Yield each substring of a complete string
|
@@ -75,19 +98,42 @@ class Redis
|
|
75
98
|
|
76
99
|
# Add all substrings of a string to redis
|
77
100
|
def add_substrings(str, score, id)
|
78
|
-
each_substring(str)
|
101
|
+
each_substring(str) do |sub|
|
102
|
+
if @max_per_substring == Float::INFINITY
|
103
|
+
add_substring(sub, score, id)
|
104
|
+
else
|
105
|
+
add_substring_limit(sub, score, id)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Add the id of an item to a substring
|
111
|
+
def add_substring(sub, score, id)
|
112
|
+
@substrings.zadd(sub, score, id)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Add the id of an item to a substring only when the number of items that
|
116
|
+
# substring stores is less then the config value of "max_per_substring".
|
117
|
+
# If the substring set is already full, check to see if the item with the
|
118
|
+
# lowest score in the substring set has a lower score than the item being added.
|
119
|
+
# If yes, remove that item and add this item to the substring set.
|
120
|
+
def add_substring_limit(sub, score, id)
|
121
|
+
count = @substrings.zcount(sub, "-inf", "inf")
|
122
|
+
if count < @max_per_substring
|
123
|
+
add_substring(sub, score, id)
|
124
|
+
else
|
125
|
+
lowest_item = @substrings.zrevrange(sub, -1, -1, { withscores: true }).last
|
126
|
+
if score > lowest_item[1]
|
127
|
+
@substrings.zrem(sub, lowest_item[0])
|
128
|
+
add_substring(sub, score, id)
|
129
|
+
end
|
130
|
+
end
|
79
131
|
end
|
80
132
|
|
81
133
|
# Remove all substrings of a string from the db
|
82
134
|
def remove_substrings(str, id)
|
83
135
|
each_substring(str) { |sub| @substrings.zrem(sub, id) }
|
84
136
|
end
|
85
|
-
|
86
|
-
# Get the id associated with an item in the db
|
87
|
-
def get_id(item)
|
88
|
-
kv_pair = @db.hgetall(@items).find { |_, v| v == item}
|
89
|
-
kv_pair.first unless kv_pair.nil?
|
90
|
-
end
|
91
137
|
end
|
92
138
|
end
|
93
139
|
end
|
@@ -3,46 +3,55 @@ class Redis
|
|
3
3
|
|
4
4
|
# Default Redis server at localhost:6379
|
5
5
|
@redis = Redis.new
|
6
|
+
|
7
|
+
# Main Redis namespace for this module
|
8
|
+
@namespace = "suggest"
|
6
9
|
|
7
|
-
@db = Redis::Namespace.new(
|
10
|
+
@db = Redis::Namespace.new(@namespace, :redis => @redis)
|
8
11
|
|
9
12
|
# Key for a Redis hash mapping ids to items we want to use for autosuggest responses
|
10
13
|
@items = "items"
|
11
14
|
|
15
|
+
# Key to a Redis hash mapping items to their respective ids
|
16
|
+
@itemids = "itemids"
|
17
|
+
|
12
18
|
# If we want to autosuggest for partial matchings of the word: 'ruby', we would
|
13
19
|
# have four sorted sets: 'autosuggest:substring:r', 'autosuggest:substring:ru',
|
14
20
|
# 'autosuggest:substring:rub', and 'autosuggest:substring:ruby'.
|
15
21
|
# Each sorted set would the id to the word 'ruby'
|
16
|
-
@substrings = Redis::Namespace.new("
|
22
|
+
@substrings = Redis::Namespace.new("#{@namespace}:sub", :redis => @redis)
|
17
23
|
|
18
24
|
# max number of ids to store per substring.
|
19
25
|
@max_per_substring = Float::INFINITY
|
20
26
|
|
21
27
|
# max number of results to return for an autosuggest query
|
22
|
-
@max_results = 5
|
28
|
+
@max_results = 5
|
23
29
|
|
24
30
|
# Key to a sorted set holding all id of items in the autosuggest database sorted
|
25
31
|
# by their score
|
26
32
|
@leaderboard = "lead"
|
27
33
|
|
28
|
-
# Leaderboard
|
34
|
+
# Leaderboard on by default
|
29
35
|
@use_leaderboard = false
|
30
36
|
|
31
37
|
# Sources to be used for Autocomplete in rails.
|
32
38
|
# Example: { Movie => :movie_title }
|
33
39
|
@rails_sources = {}
|
34
40
|
|
41
|
+
# Stores the number of items the db has for each rails source
|
42
|
+
@rails_source_sizes = Redis::Namespace.new("#{@namespace}:size", :redis => @redis)
|
43
|
+
|
35
44
|
class << self
|
36
45
|
attr_reader :redis
|
37
|
-
attr_accessor :db, :items, :substrings, :max_per_substring, :max_results,
|
38
|
-
:leaderboard, :use_leaderboard, :rails_sources
|
46
|
+
attr_accessor :namespace, :db, :items, :substrings, :max_per_substring, :max_results,
|
47
|
+
:leaderboard, :use_leaderboard, :rails_sources, :rails_source_sizes
|
39
48
|
|
40
49
|
def redis=(redis)
|
41
50
|
@redis = redis
|
42
|
-
@db = Redis::Namespace.new(
|
43
|
-
@substrings = Redis::Namespace.new("
|
51
|
+
@db = Redis::Namespace.new(@namespace, :redis => redis)
|
52
|
+
@substrings = Redis::Namespace.new("#{@namespace}:sub", :redis => redis)
|
53
|
+
@rails_source_sizes = Redis::Namespace.new("#{@namespace}:size", :redis => redis)
|
44
54
|
end
|
45
55
|
end
|
46
56
|
end
|
47
57
|
end
|
48
|
-
|
@@ -0,0 +1,100 @@
|
|
1
|
+
class Redis
|
2
|
+
module Autosuggest
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
module ClassMethods
|
5
|
+
|
6
|
+
def autosuggest(column, options={})
|
7
|
+
hash = Redis::Autosuggest.rails_sources[self]
|
8
|
+
if hash.nil?
|
9
|
+
Redis::Autosuggest.rails_sources[self] = { column => options }
|
10
|
+
else
|
11
|
+
hash[column] = options
|
12
|
+
end
|
13
|
+
|
14
|
+
# Hook onto rails callbacks to update autosuggest db if a source is modified
|
15
|
+
class_eval <<-HERE
|
16
|
+
after_create :add_to_autosuggest
|
17
|
+
def add_to_autosuggest
|
18
|
+
Redis::Autosuggest::SuggestRails.add_to_autosuggest(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
after_update :check_if_changed
|
22
|
+
def check_if_changed
|
23
|
+
Redis::Autosuggest::SuggestRails.check_if_changed(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
before_destroy :remove_from_autosuggest
|
27
|
+
def remove_from_autosuggest
|
28
|
+
Redis::Autosuggest::SuggestRails.remove_from_autosuggest(self)
|
29
|
+
end
|
30
|
+
HERE
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module SuggestRails
|
35
|
+
class << self
|
36
|
+
|
37
|
+
def init_rails_sources
|
38
|
+
Rails.application.eager_load!
|
39
|
+
Redis::Autosuggest.db.flushdb
|
40
|
+
Redis::Autosuggest.rails_sources.each do |model, attrs|
|
41
|
+
attrs.each do |column, options|
|
42
|
+
order = options[:init_order] || ""
|
43
|
+
model.order(order).find_each do |record|
|
44
|
+
puts "Adding #{record.send(column)}"
|
45
|
+
size = self.add_source_attr(record, column, options)
|
46
|
+
break if size >= options[:limit]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_to_autosuggest(record)
|
53
|
+
Redis::Autosuggest.rails_sources[record.class].each do |column, options|
|
54
|
+
self.add_source_attr(record, column, options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_source_attr(record, column, options)
|
59
|
+
item = record.send(column)
|
60
|
+
size = self.get_size(record.class, column).to_i
|
61
|
+
if size < options[:limit]
|
62
|
+
score = record.send(options[:rank_by]) unless options[:rank_by].nil?
|
63
|
+
score ||= 0
|
64
|
+
is_new_item = Redis::Autosuggest.add_with_score(item, score)
|
65
|
+
size = self.incr_size(record.class, column) if is_new_item
|
66
|
+
end
|
67
|
+
return size
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_if_changed(record)
|
71
|
+
Redis::Autosuggest.rails_sources[record.class].each_key do |column|
|
72
|
+
next unless record.send("#{column}_changed?")
|
73
|
+
old_item = record.send("#{column}_was")
|
74
|
+
score = Redis::Autosuggest.get_score(old_item)
|
75
|
+
Redis::Autosuggest.remove(old_item)
|
76
|
+
Redis::Autosuggest.add_with_score(record.send(column), score)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def remove_from_autosuggest(record)
|
81
|
+
Redis::Autosuggest.rails_sources[record.class].each_key do |column|
|
82
|
+
item = record.send(column)
|
83
|
+
item_was_in_db = Redis::Autosuggest.remove(item)
|
84
|
+
self.incr_size(record.class, column, -1) if item_was_in_db
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Get the size (how many items) of a model/attribute pair
|
89
|
+
def get_size(model, attr)
|
90
|
+
Redis::Autosuggest.rails_source_sizes.get("#{model}:#{attr}")
|
91
|
+
end
|
92
|
+
|
93
|
+
# Increment the key storing the size of a model/attribute pair
|
94
|
+
def incr_size(model, attr, incr=1)
|
95
|
+
return Redis::Autosuggest.rails_source_sizes.incrby("#{model}:#{attr}", incr)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/redis-autosuggest.gemspec
CHANGED
@@ -18,8 +18,8 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
21
|
-
gem.add_dependency("redis", "~> 3.0.
|
21
|
+
gem.add_dependency("redis", "~> 3.0.2")
|
22
22
|
gem.add_dependency("redis-namespace", "~> 1.2.1")
|
23
23
|
|
24
|
-
gem.add_development_dependency("minitest", "~> 3.
|
24
|
+
gem.add_development_dependency("minitest", "~> 4.3.3")
|
25
25
|
end
|
data/test/autosuggest_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class TestAutosuggest < MiniTest::Unit::TestCase
|
4
|
-
|
4
|
+
|
5
5
|
def self.unused_db
|
6
6
|
@unused_db ||= Redis.new(:db => TestHelper.db_picker)
|
7
7
|
end
|
@@ -44,7 +44,7 @@ class TestAutosuggest < MiniTest::Unit::TestCase
|
|
44
44
|
assert @subs.keys.size == 10
|
45
45
|
end
|
46
46
|
|
47
|
-
|
47
|
+
def test_adding_multiple_items_with_scores
|
48
48
|
Redis::Autosuggest.add_with_score("one", 1, "two", 2, "three", 3)
|
49
49
|
assert @db.hgetall(Redis::Autosuggest.items).size == 3
|
50
50
|
assert @subs.keys.size == 10
|
@@ -101,8 +101,16 @@ class TestAutosuggest < MiniTest::Unit::TestCase
|
|
101
101
|
end
|
102
102
|
|
103
103
|
def test_getting_an_items_score
|
104
|
-
|
105
|
-
|
104
|
+
Redis::Autosuggest.add_with_score(@str1, 3)
|
105
|
+
assert_equal 3, Redis::Autosuggest.get_score(@str1)
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_adding_with_substring_limit
|
109
|
+
Redis::Autosuggest.max_per_substring = 1
|
110
|
+
Redis::Autosuggest.add_with_score(@str1, 1)
|
111
|
+
Redis::Autosuggest.add_with_score("Test", 5)
|
112
|
+
item_id = Redis::Autosuggest.get_id("Test")
|
113
|
+
assert_equal [item_id], @subs.zrevrange("test", 0, -1)
|
106
114
|
end
|
107
115
|
|
108
116
|
MiniTest::Unit.after_tests { self.unused_db.flushdb }
|
data/test/file_test.rb
CHANGED
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.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 3.0.
|
21
|
+
version: 3.0.2
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 3.0.
|
29
|
+
version: 3.0.2
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: redis-namespace
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 3.
|
53
|
+
version: 4.3.3
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 3.
|
61
|
+
version: 4.3.3
|
62
62
|
description: ! "Provides autocompletions through Redis, with the ability to rank\n
|
63
63
|
\ results and integrate with Rails"
|
64
64
|
email:
|
@@ -76,8 +76,9 @@ files:
|
|
76
76
|
- lib/redis/autosuggest.rb
|
77
77
|
- lib/redis/autosuggest/config.rb
|
78
78
|
- lib/redis/autosuggest/file.rb
|
79
|
-
- lib/redis/autosuggest/
|
80
|
-
- lib/redis/autosuggest/rails.rb
|
79
|
+
- lib/redis/autosuggest/rails/railtie.rb
|
80
|
+
- lib/redis/autosuggest/rails/rake_tasks.rb
|
81
|
+
- lib/redis/autosuggest/rails/sources.rb
|
81
82
|
- lib/redis/autosuggest/version.rb
|
82
83
|
- redis-autosuggest.gemspec
|
83
84
|
- test/autosuggest_test.rb
|
@@ -1,49 +0,0 @@
|
|
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
|
-
|