smart_search 0.0.7 → 0.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b4452571bb09d489fdd980a8b151245b891470c2
4
- data.tar.gz: d5d8f1b4a301583170703bf6f7c0e322d3b1c59a
3
+ metadata.gz: 869d08c2cff4be98569eb734dfdce5d675807fc2
4
+ data.tar.gz: bc6139fd0e37f7c0fc5c9d74d056d91a5132d6e6
5
5
  SHA512:
6
- metadata.gz: 001028ede264fd11fad4bbf5a2a1c106c28fa3d5581ef23f1c5839e432b4b66286efc55152b35738187da969a606277c86bb2e2bce9b9839e0dfefe7c5ef2697
7
- data.tar.gz: 770d3e266a57b8e1adf23893c85893c2d3248e840974cbd050fad9f110930bebd8561365b377287688d2570d02173491e7a9b55b472e9969ce097b1cb06fb311
6
+ metadata.gz: 4d195f3d1ab9c0a5a7317ffc5412b4708ad440aa10e05079e5729ee3865866f79f0ddd820634ed189920811e859f6f72b648aa655a4d83ff261885a72872772f
7
+ data.tar.gz: 31f672e5448d8b491016c132f34b7288b8e057b8b98e039466c83a89d564b99c0c7781ece2812005c4e50dbff6871aa19facf20c0a378bda0ea26023f04a5cb1
data/lib/smart_search.rb CHANGED
@@ -10,11 +10,11 @@ require "smart_search_tag"
10
10
 
11
11
 
12
12
  module SmartSearch
13
-
13
+
14
14
  def self.included(base)
15
15
  base.extend ClassMethods
16
- end
17
-
16
+ end
17
+
18
18
  # Class Methods for ActiveRecord
19
19
  module ClassMethods
20
20
  # Enable SmartSearch for the current ActiveRecord model.
@@ -28,228 +28,234 @@ module SmartSearch
28
28
  if table_exists?
29
29
  # Check if search_tags exists
30
30
  if !is_smart_search? || options[:force] == true || Rails.env == "test"
31
-
31
+
32
32
  cattr_accessor :condition_default, :group_default, :tags, :order_default, :enable_similarity, :default_template_path
33
33
  send :include, InstanceMethods
34
- self.send(:after_save, :create_search_tags)
34
+ self.send(:after_save, :create_search_tags, :if => :update_search_tags?) unless options[:auto] == false
35
35
  self.send(:before_destroy, :clear_search_tags)
36
36
  self.enable_similarity ||= true
37
-
38
- attr_accessor :query_score
39
-
37
+
38
+ attr_accessor :query_score, :dont_update_search_tags
39
+
40
40
  # options zuweisen
41
41
  if options[:conditions].is_a?(String) && !options[:conditions].blank?
42
42
  self.condition_default = options[:conditions]
43
43
  elsif !options[:conditions].nil?
44
- raise ArgumentError, ":conditions must be a valid SQL Query"
44
+ raise ArgumentError, ":conditions must be a valid SQL Query"
45
45
  else
46
46
  self.condition_default = nil
47
- end
48
-
47
+ end
48
+
49
49
  self.order_default = options[:order]
50
50
 
51
51
  self.tags = options[:on] || []
52
52
  end
53
- end
53
+ end
54
54
  end
55
-
55
+
56
56
  # Verify if SmartSearch already loaded for this model
57
57
  def is_smart_search?
58
58
  self.included_modules.include?(InstanceMethods)
59
59
  end
60
-
60
+
61
61
  # defines where to look for a partial to load when displaying results for this model
62
62
  def result_template_path
63
63
  "/search/results/#{self.name.split("::").last.underscore}"
64
- end
65
-
64
+ end
65
+
66
66
  # Serach database for given search tags
67
67
  def find_by_tags(tags = "", options = {})
68
68
  if self.is_smart_search?
69
-
69
+
70
+ tags = tags.join(" ") if tags.is_a?(Array)
71
+
70
72
  # Save Data for similarity analysis
71
73
  if tags.size > 3
72
74
  self.connection.execute("INSERT INTO `#{::SmartSearchHistory.table_name}` (`query`) VALUES ('#{tags.gsub(/[^a-zA-ZäöüÖÄÜß\ ]/, '')}');")
73
- end
74
-
75
- tags = tags.split(/[\ -]/).select {|t| !t.blank?}
76
-
75
+ end
76
+
77
+ tags = tags.gsub(/[\(\)\[\]\'\"\*\%\|]/, '').split(/[\ -]/).select {|t| !t.blank?}
78
+
77
79
  # Fallback for Empty String
78
80
  tags << "#" if tags.empty?
79
-
81
+
80
82
  # Similarity
81
83
  if self.enable_similarity == true
82
- tags.map! do |t|
84
+ tags.map! do |t|
83
85
  similars = SmartSimilarity.similars(t, :increment_counter => true).join("|")
84
86
  "search_tags REGEXP '#{similars}'"
85
- end
86
-
87
+ end
88
+
87
89
  else
88
90
  tags.map! {|t| "search_tags LIKE '%#{t}%'"}
89
- end
90
-
91
+ end
92
+
91
93
  # Load ranking from Search tags
92
94
  result_ids = []
93
95
  result_scores = {}
94
- SmartSearchTag.connection.select_all("select entry_id, sum(boost) as score, group_concat(search_tags) as grouped_tags
95
- from smart_search_tags where `table_name`= '#{self.table_name}' and
96
-
97
- (#{tags.join(' OR ')}) group by entry_id having (#{tags.join(' AND ').gsub('search_tags', 'grouped_tags')}) order by score DESC").each do |r|
98
- result_ids << r["entry_id"].to_i
96
+ SmartSearchTag.connection.select_all("select entry_id, sum(boost) as score, group_concat(search_tags) as grouped_tags
97
+ from smart_search_tags where `table_name`= '#{self.table_name}' and
98
+
99
+ (#{tags.join(' OR ')}) group by entry_id having (#{tags.join(' AND ').gsub('search_tags', 'grouped_tags')}) order by score DESC").each do |r|
100
+ result_ids << r["entry_id"].to_i
99
101
  result_scores[r["entry_id"].to_i] = r['score'].to_f
100
- end
101
-
102
+ end
103
+
102
104
  # Enable unscoped searching
103
105
  if options[:unscoped] == true
104
106
  results = self.unscoped.where(:id => result_ids)
105
- else
107
+ else
106
108
  results = self.where(:id => result_ids)
107
- end
108
-
109
-
110
-
109
+ end
110
+
111
111
  if options[:conditions]
112
112
  results = results.where(options[:conditions])
113
113
  end
114
-
114
+
115
115
  if !self.condition_default.blank?
116
116
  results = results.where(self.condition_default)
117
- end
118
-
119
- if options[:group]
117
+ end
118
+
119
+ if options[:group]
120
120
  results = results.group(options[:group])
121
- end
122
-
121
+ end
122
+
123
123
  if options[:order] || self.order_default
124
124
  results = results.order(options[:order] || self.order_default)
125
125
  else
126
126
  ordered_results = []
127
- results.each do |r|
127
+ results.each do |r|
128
128
  r.query_score = result_scores[r.id]
129
129
  ordered_results[result_ids.index(r.id)] = r
130
- end
131
-
130
+ end
131
+
132
132
  results = ordered_results.compact
133
- end
134
-
133
+ end
134
+
135
135
  return results
136
- else
136
+ else
137
137
  raise "#{self.inspect} is not a SmartSearch"
138
- end
138
+ end
139
139
  end
140
-
140
+
141
141
  # reload search_tags for entire table based on the attributes defined in ':on' option passed to the 'smart_search' method
142
142
  def set_search_index
143
143
  s = self.all.size.to_f
144
144
  self.all.each_with_index do |a, i|
145
145
  a.create_search_tags
146
146
  done = ((i+1).to_f/s)*100
147
- printf "Set search index for #{self.name}: #{done}%% \r"
148
- end
149
- end
150
-
147
+ end
148
+ end
149
+
151
150
  # Load all search tags for this table into similarity index
152
151
  def set_similarity_index
153
-
154
152
  search_tags_list = self.connection.select_all("SELECT search_tags from #{SmartSearchTag.table_name} where `table_name` = #{self.table_name}").map {|r| r["search_tags"]}
155
-
153
+
156
154
  SmartSimilarity.create_from_text(search_tags_list.join(" "))
157
- end
158
-
159
- end
160
-
155
+ end
156
+
157
+ end
158
+
161
159
  # Instance Methods for ActiveRecord
162
160
  module InstanceMethods
163
-
161
+
164
162
  # Load the result template path for this instance
165
163
  def result_template_path
166
164
  self.class.result_template_path
167
- end
168
-
165
+ end
166
+
167
+ def dont_update_search_tags!
168
+ self.dont_update_search_tags = true
169
+ end
170
+
171
+ def update_search_tags?
172
+ !self.dont_update_search_tags
173
+ end
174
+
169
175
  # create search tags for this very record based on the attributes defined in ':on' option passed to the 'Class.smart_search' method
170
176
  def create_search_tags
171
177
  tags = []
172
-
178
+
173
179
  self.class.tags.each do |tag|
174
-
180
+
175
181
  if !tag.is_a?(Hash)
176
- tag = {:field_name => tag, :boost => 1, :search_tags => ""}
182
+ tag = {:field_name => tag, :boost => 1, :search_tags => ""}
177
183
  else
178
184
  tag[:search_tags] = ""
179
185
  tag[:boost] ||= 1
180
- end
181
-
186
+ end
187
+
182
188
  if tag[:field_name].is_a?(Symbol)
183
189
  tag[:search_tags] << self.send(tag[:field_name]).to_s
184
190
  elsif tag[:field_name].is_a?(String)
185
- tag_methods = tag[:field_name].split(".")
191
+ tag_methods = tag[:field_name].split(".")
186
192
  tagx = self.send(tag_methods[0])
187
193
  tag_methods[1..-1].each do |x|
188
194
  tagx = tagx.send(x) rescue ""
189
195
  end
190
- tag[:search_tags] << tagx.to_s
196
+ tag[:search_tags] << tagx.to_s
191
197
  end
192
-
193
- tag[:search_tags] = tag[:search_tags].split(" ").uniq.join(" ").downcase.clear_html
198
+
199
+ tag[:search_tags] = tag[:search_tags].split(" ").uniq.join(" ").downcase.clear_html
194
200
  tags << tag
195
201
  end
196
-
197
-
202
+
203
+
198
204
  self.clear_search_tags
199
-
205
+
200
206
  # Merge search tags with same boost
201
207
  @merged_tags = {}
202
-
208
+
203
209
  tags.each do |t|
204
210
  boost = t[:boost]
205
-
211
+
206
212
  if @merged_tags[boost]
207
-
213
+
208
214
  @merged_tags[boost][:field_name] << ",#{t[:field_name]}"
209
215
  @merged_tags[boost][:search_tags] << " #{t[:search_tags]}"
210
216
  else
211
217
  @merged_tags[boost] = {:field_name => "#{t[:field_name]}", :search_tags => t[:search_tags], :boost => boost }
212
- end
213
-
214
- end
215
-
218
+ end
219
+
220
+ end
221
+
216
222
  @merged_tags.values.each do |t|
217
223
  if !t[:search_tags].blank? && t[:search_tags].size > 1
218
- SmartSearchTag.create(t.merge!(:table_name => self.class.table_name, :entry_id => self.id, :search_tags => t[:search_tags].strip.split(" ").uniq.join(" ")))
219
- end
224
+ SmartSearchTag.create(t.merge!(:table_name => self.class.table_name, :entry_id => self.id, :search_tags => t[:search_tags].strip.split(" ").uniq.join(" ")))
225
+ end
220
226
  end
221
-
227
+
222
228
  end
223
-
229
+
224
230
  # Remove search data for the instance from the index
225
231
  def clear_search_tags
226
232
  if !self.id.nil?
227
- SmartSearchTag.connection.execute("DELETE from #{SmartSearchTag.table_name} where `table_name` = '#{self.class.table_name}' and entry_id = #{self.id}")
228
- end
229
- end
230
-
231
- end
232
-
233
+ SmartSearchTag.connection.execute("DELETE from #{SmartSearchTag.table_name} where `table_name` = '#{self.class.table_name}' and entry_id = #{self.id}") rescue nil
234
+ end
235
+ end
236
+
237
+ end
238
+
233
239
 
234
240
  class Config
235
-
241
+
236
242
  cattr_accessor :search_models
237
243
  cattr_accessor :public_models
238
-
244
+
239
245
  self.search_models = []
240
246
  self.public_models = []
241
-
247
+
242
248
  def self.get_search_models
243
- self.search_models.map {|m| m.constantize}
249
+ self.search_models.map {|m| m.constantize}
244
250
  end
245
-
251
+
246
252
  def self.get_public_models
247
- self.public_models.map {|m| m.constantize}
248
- end
249
-
250
- end
251
-
252
-
253
+ self.public_models.map {|m| m.constantize}
254
+ end
255
+
256
+ end
257
+
258
+
253
259
  end
254
260
 
255
261
 
@@ -4,7 +4,7 @@ namespace :smart_search do
4
4
  require File.expand_path("../../smart_similarity", __FILE__)
5
5
  SmartSimilarity.load_from_query_history
6
6
  end
7
-
7
+
8
8
  desc "Load similarity data from file - Use FILE=path/to/file to specify file"
9
9
  task :similarity_from_file => :environment do
10
10
  require File.expand_path("../../smart_similarity", __FILE__)
@@ -12,47 +12,47 @@ namespace :smart_search do
12
12
  raise ArgumentError, "No file specified. "
13
13
  elsif !File.exist?(ENV['FILE_PATH'])
14
14
  raise ArgumentError, "File not found "
15
- else
15
+ else
16
16
  SmartSimilarity.load_file(ENV['FILE_PATH'])
17
- end
17
+ end
18
18
  end
19
-
19
+
20
20
  desc "Load similarity data from url - Use URL=http://.../ to specify url - Requires 'curl'"
21
21
  task :similarity_from_url => :environment do
22
22
  require File.expand_path("../../smart_similarity", __FILE__)
23
23
  if ENV['URL'].nil?
24
24
  raise ArgumentError, "No URL specified. "
25
- else
25
+ else
26
26
  SmartSimilarity.load_url(ENV['URL'])
27
- end
27
+ end
28
28
  end
29
-
30
-
31
-
29
+
30
+
31
+
32
32
  desc "load ignore words list"
33
33
  task :load_ignore_words => :environment do
34
34
  require File.expand_path("../../smart_search_ignore_word", __FILE__)
35
-
35
+
36
36
  dic_path = File.expand_path("../../../dictionaries/*", __FILE__)
37
-
37
+
38
38
  raise dic_path.inspect
39
-
39
+
40
40
  dic_folders = Dir.glob(dic_path).select {|d| File.directory?(d)}
41
-
41
+
42
42
  dic_folders.each do |folder|
43
43
  locale = folder.split("/").last
44
44
  word_file = File.join(folder, "#{locale}.ignore_words.dic")
45
45
  if File.exists?(word_file)
46
46
  File.open(word_file, "r").each_line do |word|
47
47
  SmartSearchIgnoreWord.create(:word => word.strip.downcase, :locale => locale)
48
- end
49
- end
50
- end
51
- end
52
-
53
-
54
-
55
-
56
- end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+
54
+
55
+
56
+ end
57
57
 
58
58
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Eck
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-15 00:00:00.000000000 Z
11
+ date: 2017-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 3.2.9
19
+ version: 4.0.4
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 3.2.9
26
+ version: 4.0.4
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: amatch
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: friendly_extensions
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 0.0.61
47
+ version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 0.0.61
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: mysql2
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -69,7 +69,7 @@ dependencies:
69
69
  description: SmartSearch adds full-text search functions to ActiveRecord running with
70
70
  MySQL, including search for similiar words. Its fast, simple, and works with almost
71
71
  zero-config!
72
- email: it-support@friends-systems.de
72
+ email: florian.eck@el-digital.de
73
73
  executables: []
74
74
  extensions: []
75
75
  extra_rdoc_files: []
@@ -109,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
109
  version: '0'
110
110
  requirements: []
111
111
  rubyforge_project:
112
- rubygems_version: 2.2.1
112
+ rubygems_version: 2.6.12
113
113
  signing_key:
114
114
  specification_version: 4
115
115
  summary: Simple, easy to use search MySQL based search for ActiveRecord
@@ -120,4 +120,3 @@ test_files:
120
120
  - test/unit/01_smart_search_test.rb
121
121
  - test/unit/02_smart_search_similarity_test.rb
122
122
  - test/unit/03_smart_search_boost_test.rb
123
- has_rdoc: