smart_search 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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: