soulmate_rails 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm 1.9.3-p385@soulmate_rails --create
1
+ rvm 1.9.3-p194@soulmate_rails --create
data/Rakefile CHANGED
@@ -20,7 +20,7 @@ end
20
20
 
21
21
  desc 'Open an irb session preloaded with this library'
22
22
  task :console do
23
- sh 'irb -rubygems -I lib:spec -r soulmate_rails.rb -r spec_helper.rb'
23
+ sh 'irb -rubygems -I lib:spec -r irb/completion -r soulmate_rails.rb -r spec_helper.rb'
24
24
  end
25
25
 
26
26
  desc 'Release the gem'
data/lib/soulmate/base.rb CHANGED
@@ -9,15 +9,15 @@ module Soulmate
9
9
  end
10
10
 
11
11
  def base
12
- "soulmate-index:#{type}"
12
+ "soulmate-index:#{Soulmate.cache_namespace}_#{type}"
13
13
  end
14
14
 
15
15
  def database
16
- "soulmate-data:#{type}"
16
+ "soulmate-data:#{Soulmate.cache_namespace}_#{type}"
17
17
  end
18
18
 
19
19
  def cachebase
20
- "soulmate-cache:#{type}"
20
+ "soulmate-cache:#{Soulmate.cache_namespace}_#{type}"
21
21
  end
22
22
  end
23
23
  end
@@ -8,7 +8,7 @@ module Soulmate
8
8
  Soulmate.stop_words.include?(w)
9
9
  end
10
10
  words.map do |w|
11
- (MIN_COMPLETE-1..(w.length-1)).map{ |l| w[0..l] }
11
+ (Soulmate.min_complete-1..(w.length-1)).map{ |l| w[0..l] }
12
12
  end.flatten.uniq
13
13
  end
14
14
 
@@ -2,10 +2,10 @@ module Soulmate
2
2
  class Matcher < Base
3
3
 
4
4
  def matches_for_term(term, options = {})
5
- options = { :limit => 5, :cache => true }.merge(options)
6
-
5
+ options = { :limit => Soulmate.max_results, :cache => true }.merge(options)
6
+
7
7
  words = normalize(term).split(' ').reject do |w|
8
- w.size < MIN_COMPLETE or Soulmate.stop_words.include?(w)
8
+ w.size < Soulmate.min_complete or Soulmate.stop_words.include?(w)
9
9
  end.sort
10
10
 
11
11
  return [] if words.empty?
@@ -15,7 +15,7 @@ module Soulmate
15
15
  if !options[:cache] || !Soulmate.redis.exists(cachekey)
16
16
  interkeys = words.map { |w| "#{base}:#{w}" }
17
17
  Soulmate.redis.zinterstore(cachekey, interkeys)
18
- Soulmate.redis.expire(cachekey, 10 * 60) # expire after 10 minutes
18
+ Soulmate.redis.expire(cachekey, Soulmate.cache_time)
19
19
  end
20
20
 
21
21
  ids = Soulmate.redis.zrevrange(cachekey, 0, options[:limit] - 1)
@@ -26,6 +26,7 @@ module Soulmate
26
26
  else
27
27
  []
28
28
  end
29
+
29
30
  end
30
31
  end
31
32
  end
@@ -17,6 +17,7 @@ module Soulmate
17
17
  extend self
18
18
 
19
19
  MIN_COMPLETE = 2
20
+
20
21
  DEFAULT_STOP_WORDS = ["vs", "at", "the"]
21
22
 
22
23
  def redis=(server)
@@ -51,4 +52,43 @@ module Soulmate
51
52
  @stop_words = Array(arr).flatten
52
53
  end
53
54
 
55
+ def min_complete
56
+ @min_complete ||= MIN_COMPLETE
57
+ end
58
+
59
+ def min_complete=(min_len)
60
+ if min_len.is_a? Integer
61
+ @min_complete = min_len unless min_len < 1 || min_len > 5
62
+ end
63
+ end
64
+
65
+ def cache_time
66
+ # default to 10 minutes
67
+ @cache_time ||= 10 * 60
68
+ end
69
+
70
+ def cache_time=(time_period)
71
+ if time_period.is_a? Integer
72
+ @cache_time = time_period unless time_period < 1
73
+ end
74
+ end
75
+
76
+ def cache_namespace
77
+ @cache_namespace
78
+ end
79
+
80
+ def cache_namespace=(namespace)
81
+ @cache_namespace = namespace
82
+ end
83
+
84
+ def max_results
85
+ # default to 10 max results returned
86
+ @max_results ||= 10
87
+ end
88
+
89
+ def max_results=(max_num)
90
+ if max_num.is_a? Integer
91
+ @max_results = max_num unless max_num < 1
92
+ end
93
+ end
54
94
  end
@@ -12,7 +12,7 @@ module SoulmateRails
12
12
  loader = instance_variable_get("@#{self.class.name_for(attribute)}_loader") || instance_variable_set("@#{self.class.name_for(attribute)}_loader", Soulmate::Loader.new(self.class.name_for(attribute)))
13
13
  item = {
14
14
  'id' => "#{attribute}_#{self.id}",
15
- 'term' => send(attribute),
15
+ 'term' => send(attribute).encode('UTF-8'),
16
16
  'score' => ( respond_to?(options[:score]) ? send(options[:score]) : options[:score] )
17
17
  }
18
18
 
@@ -59,6 +59,22 @@ module SoulmateRails
59
59
  opts = opts.empty? ? {} : opts.first
60
60
  search_by(attribute, term, opts)
61
61
  end
62
+
63
+ # use only redis cache without touching backend database
64
+ define_singleton_method "search_cache_by_#{attribute}" do |term, *opts|
65
+ opts = opts.empty? ? {} : opts.first
66
+ search_cache_by(attribute, term, opts)
67
+ end
68
+
69
+ # define utility function to clean out cached data
70
+ define_singleton_method "flush_cache_by_#{attribute}" do
71
+ flush_cache(attribute)
72
+ end
73
+
74
+ # define utility function to reload data from database
75
+ define_singleton_method "reload_cache_by_#{attribute}" do |options|
76
+ reload_cache(attribute, options)
77
+ end
62
78
  end
63
79
 
64
80
  def search_by(attribute, term, options={})
@@ -81,6 +97,47 @@ module SoulmateRails
81
97
  def normalized_class_name
82
98
  self.name.gsub('::', '_').downcase
83
99
  end
100
+
101
+ def flush_cache(attribute)
102
+ loader = instance_variable_get("@#{name_for(attribute)}") || instance_variable_set("@#{name_for(attribute)}", Soulmate::Loader.new(name_for(attribute)))
103
+
104
+ # delete the sorted sets for this type
105
+ phrases = Soulmate.redis.keys(loader.base + "*")
106
+
107
+ # delete cached sets for previous
108
+ cache_phrases = Soulmate.redis.keys(loader.cachebase + "*")
109
+
110
+ Soulmate.redis.pipelined do
111
+ phrases.each do |p|
112
+ Soulmate.redis.del(p)
113
+ end
114
+
115
+ cache_phrases.each do |p|
116
+ Soulmate.redis.del(p)
117
+ end
118
+ end
119
+
120
+ # delete the data stored for this type
121
+ Soulmate.redis.del(loader.database)
122
+ end
123
+
124
+ # example call: City.reload_cache(:name, {:score => :autocomplete_score, :data => :autocomplete_data})
125
+ # example call: City.reload_cache_by_name({:score => :autocomplete_score, :data => :autocomplete_data})
126
+ def reload_cache(attribute, options)
127
+ flush_cache(attribute)
128
+ self.find_each { |object| object.update_index_for(attribute, options) }
129
+ end
130
+
131
+ # define a mathod to return results from cache instead of connecting to backend database
132
+ def search_cache_by(attribute, term, options={})
133
+ matcher = instance_variable_get("@#{name_for(attribute)}_matcher") || instance_variable_set("@#{name_for(attribute)}_matcher", Soulmate::Matcher.new(name_for(attribute)))
134
+ matches = matcher.matches_for_term(term, options)
135
+
136
+ res = []
137
+ matches.each {|m| res << [m['id'].split('_')[-1].to_i, m['data']] }
138
+
139
+ res
140
+ end
84
141
  end
85
142
  end
86
143
  end
@@ -7,9 +7,23 @@ module SoulmateRails
7
7
  end
8
8
 
9
9
  initializer 'soulmate_rails.set_configs' do |app|
10
- options = app.config.soulmate_rails
11
-
12
- Soulmate.redis = options[:redis] if options[:redis]
10
+ # configuration file for redis server and soulmate
11
+ Soulmate.cache_namespace ||= "#{app.engine_name}_#{Rails.env}"
12
+ redis_config_file = "config/redis_server.yml"
13
+ if File.exists?(redis_config_file)
14
+ file = YAML.load_file(redis_config_file)
15
+ Soulmate.redis = file[:redis_url] if file[:redis_url]
16
+ Soulmate.cache_time = file[:cache_time] if file[:cache_time]
17
+ Soulmate.max_results = file[:max_results] if file[:max_results]
18
+ end
19
+ # configuration file for stopping words
20
+ stop_words_file = "config/stopping_words.yml"
21
+ if File.exists?(stop_words_file)
22
+ stopping_words = []
23
+ s_file = YAML.load_file(stop_words_file)
24
+ s_file.each_line { |line| stopping_words.push(line) }
25
+ Soulmate.stop_words = stopping_words
26
+ end
13
27
  end
14
28
  end
15
29
  end
@@ -1,7 +1,7 @@
1
1
  module SoulmateRails
2
2
  MAJOR = 0
3
3
  MINOR = 3
4
- PATCH = 0
4
+ PATCH = 1
5
5
 
6
6
  VERSION = [MAJOR, MINOR, PATCH].compact.join('.')
7
7
  end
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  s.authors = ["Dhruva Sagar"]
14
14
  s.homepage = "http://github.com/dhruvasagar/soulmate_rails"
15
15
  s.summary = "Redis-backed autocompletion engine for Rails"
16
- s.description = "Soulmate Rails is a tool to help solve the common problem of developing a fast autocomplete feature for Rails. It uses Redis's sorted sets to build an index of partial words and corresponding top matches."
16
+ s.description = "Soulmate Rails is a tool to help solve the common problem of developing a fast autocomplete feature for Rails. It uses Redis's sorted sets to build an index of partial words and corresponding top matches. Modified by Jim Zhan to add utility functions and for bug fixing."
17
17
 
18
18
  s.files = `git ls-files`.split("\n")
19
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
  s.require_paths = ["lib"]
24
24
 
25
25
  s.add_runtime_dependency 'redis', '>= 2.0'
26
+ s.add_runtime_dependency 'json', '>= 1.7.7'
26
27
  s.add_runtime_dependency 'multi_json', '>= 1.0'
27
28
  s.add_runtime_dependency 'activesupport', '>= 0'
28
29
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: soulmate_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
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: 2013-04-19 00:00:00.000000000 Z
12
+ date: 2013-06-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '2.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: json
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 1.7.7
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.7.7
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: multi_json
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -125,7 +141,8 @@ dependencies:
125
141
  version: '0'
126
142
  description: Soulmate Rails is a tool to help solve the common problem of developing
127
143
  a fast autocomplete feature for Rails. It uses Redis's sorted sets to build an index
128
- of partial words and corresponding top matches.
144
+ of partial words and corresponding top matches. Modified by Jim Zhan to add utility
145
+ functions and for bug fixing.
129
146
  email:
130
147
  - dhruva.sagar@gmail.com
131
148
  executables: []
@@ -172,7 +189,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
172
189
  version: '0'
173
190
  segments:
174
191
  - 0
175
- hash: -1107948345985026072
192
+ hash: 1304314171883105113
176
193
  required_rubygems_version: !ruby/object:Gem::Requirement
177
194
  none: false
178
195
  requirements:
@@ -181,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
198
  version: '0'
182
199
  segments:
183
200
  - 0
184
- hash: -1107948345985026072
201
+ hash: 1304314171883105113
185
202
  requirements: []
186
203
  rubyforge_project:
187
204
  rubygems_version: 1.8.23