autosuggest 0.1.0 → 0.1.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +30 -31
- data/lib/autosuggest.rb +28 -21
- data/lib/autosuggest/version.rb +1 -1
- metadata +14 -60
- data/.gitignore +0 -9
- data/Gemfile +0 -4
- data/Rakefile +0 -8
- data/autosuggest.gemspec +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bda23aeaee3abc15c45b52ddc2d64943de44a164f11d3a33de234171126b209c
|
4
|
+
data.tar.gz: de6f64ac9ceb628e55e275080a45ac8cf0f5605a5e80767350c264adc92266a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a7a317190aba2237a7b98b6b2cce8ed656eeb44f7c57edd6e19644700fd2c8268c5086201d44d0186f1cabd513e365d471ff2abc4e14d0963989cac55b676f1
|
7
|
+
data.tar.gz: d5dfe7b13390ef216d1f3ab614c4b6c83177d68ff4fef2545e0f34d92936f27cbd077fa44175393a487b6a398c216a51677add321521c97c4db9753e35c6bfbd
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015-2021 Andrew Kane
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -4,6 +4,16 @@ Generate autocomplete suggestions based on what your users search
|
|
4
4
|
|
5
5
|
:tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
|
6
6
|
|
7
|
+
[](https://github.com/ankane/autosuggest/actions)
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application’s Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'autosuggest'
|
15
|
+
```
|
16
|
+
|
7
17
|
## How It Works
|
8
18
|
|
9
19
|
#### Start with the most popular queries
|
@@ -53,14 +63,12 @@ There are two ways to build the corpus, which can be used together.
|
|
53
63
|
autosuggest.add_concept "brand", Brand.pluck(:name)
|
54
64
|
```
|
55
65
|
|
56
|
-
####
|
66
|
+
#### Filter words
|
57
67
|
|
58
|
-
[Profanity](https://github.com/tjackiw/obscenity/blob/master/config/blacklist.yml) is
|
59
|
-
|
60
|
-
Add custom words with:
|
68
|
+
[Profanity](https://github.com/tjackiw/obscenity/blob/master/config/blacklist.yml) is blocked by default. Add custom words with:
|
61
69
|
|
62
70
|
```ruby
|
63
|
-
autosuggest.
|
71
|
+
autosuggest.block_words ["boom"]
|
64
72
|
```
|
65
73
|
|
66
74
|
#### Profit
|
@@ -71,9 +79,7 @@ Get suggestions with:
|
|
71
79
|
autosuggest.suggestions
|
72
80
|
```
|
73
81
|
|
74
|
-
Filter queries without results and you’re set.
|
75
|
-
|
76
|
-
We also prefer to have someone manually approve them by hand.
|
82
|
+
Filter queries without results and you’re set. We also prefer to have someone manually approve them by hand.
|
77
83
|
|
78
84
|
## Full Example
|
79
85
|
|
@@ -81,40 +87,24 @@ We also prefer to have someone manually approve them by hand.
|
|
81
87
|
top_queries = Search.group("LOWER(query)")
|
82
88
|
.having("COUNT(DISTINCT user_id) >= 5")
|
83
89
|
.count("DISTINCT user_id")
|
90
|
+
product_names = Product.pluck(:name)
|
91
|
+
brand_names = Brand.pluck(:name)
|
84
92
|
|
85
93
|
autosuggest = Autosuggest.new(top_queries)
|
86
|
-
|
87
|
-
# create corpus with product names and brand names
|
88
|
-
autosuggest.parse_words Product.pluck(:name)
|
89
|
-
brand_names = Brand.pluck(:name)
|
94
|
+
autosuggest.parse_words product_names
|
90
95
|
autosuggest.add_concept "brand", brand_names
|
91
|
-
|
92
|
-
# prefer brand names
|
93
96
|
autosuggest.prefer brand_names
|
94
|
-
|
95
|
-
# prevent false positives for duplicates
|
96
97
|
autosuggest.not_duplicates [["straws", "straus"]]
|
98
|
+
autosuggest.block_words ["boom"]
|
97
99
|
|
98
|
-
# blacklist words
|
99
|
-
autosuggest.blacklist_words ["boom"]
|
100
|
-
|
101
|
-
# print suggestions
|
102
100
|
puts autosuggest.pretty_suggestions
|
103
101
|
# or
|
104
|
-
|
105
|
-
```
|
106
|
-
|
107
|
-
## Installation
|
108
|
-
|
109
|
-
Add this line to your application’s Gemfile:
|
110
|
-
|
111
|
-
```ruby
|
112
|
-
gem 'autosuggest'
|
102
|
+
suggestions = autosuggest.suggestions
|
113
103
|
```
|
114
104
|
|
115
|
-
##
|
105
|
+
## History
|
116
106
|
|
117
|
-
|
107
|
+
View the [changelog](https://github.com/ankane/autosuggest/blob/master/CHANGELOG.md)
|
118
108
|
|
119
109
|
## Contributing
|
120
110
|
|
@@ -124,3 +114,12 @@ Everyone is encouraged to help improve this project. Here are a few ways you can
|
|
124
114
|
- Fix bugs and [submit pull requests](https://github.com/ankane/autosuggest/pulls)
|
125
115
|
- Write, clarify, or fix documentation
|
126
116
|
- Suggest or add new features
|
117
|
+
|
118
|
+
To get started with development:
|
119
|
+
|
120
|
+
```sh
|
121
|
+
git clone https://github.com/ankane/autosuggest.git
|
122
|
+
cd autosuggest
|
123
|
+
bundle install
|
124
|
+
bundle exec rake test
|
125
|
+
```
|
data/lib/autosuggest.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
|
-
|
2
|
-
require "
|
1
|
+
# stdlib
|
2
|
+
require "set"
|
3
3
|
require "yaml" # for obscenity
|
4
|
+
|
5
|
+
# dependencies
|
6
|
+
require "lingua/stemmer"
|
4
7
|
require "obscenity"
|
5
8
|
|
9
|
+
# modules
|
10
|
+
require "autosuggest/version"
|
11
|
+
|
6
12
|
class Autosuggest
|
7
13
|
def initialize(top_queries)
|
8
14
|
@top_queries = top_queries
|
9
15
|
@concepts = {}
|
10
16
|
@words = Set.new
|
11
17
|
@non_duplicates = Set.new
|
18
|
+
@blocked_words = Set.new
|
12
19
|
@blacklisted_words = Set.new
|
13
20
|
@preferred_queries = {}
|
14
21
|
@profane_words = Set.new(Obscenity::Base.blacklist)
|
@@ -42,7 +49,14 @@ class Autosuggest
|
|
42
49
|
end
|
43
50
|
end
|
44
51
|
|
52
|
+
def block_words(words)
|
53
|
+
words.each do |word|
|
54
|
+
@blocked_words << word.downcase
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
45
58
|
def blacklist_words(words)
|
59
|
+
warn "[autosuggest] blacklist_words is deprecated. Use block_words instead."
|
46
60
|
words.each do |word|
|
47
61
|
@blacklisted_words << word.downcase
|
48
62
|
end
|
@@ -99,19 +113,20 @@ class Autosuggest
|
|
99
113
|
# exclude misspellings that are not brands
|
100
114
|
misspelling = @words.any? && misspellings?(query)
|
101
115
|
|
102
|
-
profane =
|
103
|
-
|
104
|
-
blacklisted =
|
116
|
+
profane = blocked?(query, @profane_words)
|
117
|
+
blocked = blocked?(query, @blocked_words)
|
118
|
+
blacklisted = blocked?(query, @blacklisted_words)
|
105
119
|
|
106
120
|
notes = []
|
107
121
|
notes << "duplicate of #{duplicate}" if duplicate
|
108
122
|
notes.concat(concepts)
|
109
123
|
notes << "misspelling" if misspelling
|
110
124
|
notes << "profane" if profane
|
125
|
+
notes << "blocked" if blocked
|
111
126
|
notes << "blacklisted" if blacklisted
|
112
127
|
notes << "originally #{original_query}" if original_query
|
113
128
|
|
114
|
-
{
|
129
|
+
result = {
|
115
130
|
query: query,
|
116
131
|
original_query: original_query,
|
117
132
|
score: count,
|
@@ -119,9 +134,11 @@ class Autosuggest
|
|
119
134
|
concepts: concepts,
|
120
135
|
misspelling: misspelling,
|
121
136
|
profane: profane,
|
122
|
-
|
123
|
-
notes: notes
|
137
|
+
blocked: blocked
|
124
138
|
}
|
139
|
+
result[:blacklisted] = blacklisted if @blacklisted_words.any?
|
140
|
+
result[:notes] = notes
|
141
|
+
result
|
125
142
|
end
|
126
143
|
end
|
127
144
|
|
@@ -144,9 +161,9 @@ class Autosuggest
|
|
144
161
|
true
|
145
162
|
end
|
146
163
|
|
147
|
-
def
|
164
|
+
def blocked?(query, blocked_words)
|
148
165
|
recurse(tokenize(query)).each do |terms|
|
149
|
-
return true if terms.any? { |t|
|
166
|
+
return true if terms.any? { |t| blocked_words.include?(t) }
|
150
167
|
end
|
151
168
|
false
|
152
169
|
end
|
@@ -173,7 +190,7 @@ class Autosuggest
|
|
173
190
|
str.to_s.downcase.split(" ")
|
174
191
|
end
|
175
192
|
|
176
|
-
# from
|
193
|
+
# from https://blog.lojic.com/2008/09/04/how-to-write-a-spelling-corrector-in-ruby/
|
177
194
|
LETTERS = ("a".."z").to_a.join + "'"
|
178
195
|
def edits(word)
|
179
196
|
n = word.length
|
@@ -189,14 +206,4 @@ class Autosuggest
|
|
189
206
|
def normalize_query(query)
|
190
207
|
tokenize(query.to_s.gsub("&", "and")).map { |q| Lingua.stemmer(q) }.sort.join
|
191
208
|
end
|
192
|
-
|
193
|
-
# TODO remove ActiveSupport dependency
|
194
|
-
|
195
|
-
def singularize(str)
|
196
|
-
str.singularize
|
197
|
-
end
|
198
|
-
|
199
|
-
def pluralize(str)
|
200
|
-
str.pluralize
|
201
|
-
end
|
202
209
|
end
|
data/lib/autosuggest/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: autosuggest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
|
-
autorequire:
|
9
|
-
bindir:
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-stemmer
|
@@ -38,66 +38,22 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
|
42
|
-
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '1.7'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '1.7'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rake
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '10.0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '10.0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: minitest
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
|
-
description:
|
84
|
-
email:
|
85
|
-
- andrew@chartkick.com
|
41
|
+
description:
|
42
|
+
email: andrew@ankane.org
|
86
43
|
executables: []
|
87
44
|
extensions: []
|
88
45
|
extra_rdoc_files: []
|
89
46
|
files:
|
90
|
-
-
|
91
|
-
-
|
47
|
+
- CHANGELOG.md
|
48
|
+
- LICENSE.txt
|
92
49
|
- README.md
|
93
|
-
- Rakefile
|
94
|
-
- autosuggest.gemspec
|
95
50
|
- lib/autosuggest.rb
|
96
51
|
- lib/autosuggest/version.rb
|
97
52
|
homepage: https://github.com/ankane/autosuggest
|
98
|
-
licenses:
|
53
|
+
licenses:
|
54
|
+
- MIT
|
99
55
|
metadata: {}
|
100
|
-
post_install_message:
|
56
|
+
post_install_message:
|
101
57
|
rdoc_options: []
|
102
58
|
require_paths:
|
103
59
|
- lib
|
@@ -105,17 +61,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
61
|
requirements:
|
106
62
|
- - ">="
|
107
63
|
- !ruby/object:Gem::Version
|
108
|
-
version: '
|
64
|
+
version: '2.4'
|
109
65
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
66
|
requirements:
|
111
67
|
- - ">="
|
112
68
|
- !ruby/object:Gem::Version
|
113
69
|
version: '0'
|
114
70
|
requirements: []
|
115
|
-
|
116
|
-
|
117
|
-
signing_key:
|
71
|
+
rubygems_version: 3.2.3
|
72
|
+
signing_key:
|
118
73
|
specification_version: 4
|
119
74
|
summary: Generate autocomplete suggestions based on what your users search
|
120
75
|
test_files: []
|
121
|
-
has_rdoc:
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
data/autosuggest.gemspec
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require "autosuggest/version"
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "autosuggest"
|
8
|
-
spec.version = Autosuggest::VERSION
|
9
|
-
spec.authors = ["Andrew Kane"]
|
10
|
-
spec.email = ["andrew@chartkick.com"]
|
11
|
-
|
12
|
-
spec.summary = "Generate autocomplete suggestions based on what your users search"
|
13
|
-
spec.homepage = "https://github.com/ankane/autosuggest"
|
14
|
-
|
15
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
|
-
spec.bindir = "exe"
|
17
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
-
spec.require_paths = ["lib"]
|
19
|
-
|
20
|
-
spec.add_dependency "ruby-stemmer"
|
21
|
-
spec.add_dependency "obscenity"
|
22
|
-
|
23
|
-
spec.add_development_dependency "bundler", "~> 1.7"
|
24
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
-
spec.add_development_dependency "minitest"
|
26
|
-
end
|