awesome_search 1.0.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.
- data/LICENSE +20 -0
- data/README.rdoc +121 -0
- data/Rakefile +72 -0
- data/VERSION +1 -0
- data/awesome_search.gemspec +70 -0
- data/init.rb +1 -0
- data/lib/awesome/definitions/bits.rb +74 -0
- data/lib/awesome/definitions/filters.rb +72 -0
- data/lib/awesome/definitions/locales.rb +69 -0
- data/lib/awesome/definitions/types.rb +93 -0
- data/lib/awesome/search.rb +146 -0
- data/lib/awesome/super_search.rb +16 -0
- data/lib/awesome/triage.rb +122 -0
- data/lib/awesome_search.rb +7 -0
- data/rails/init.rb +3 -0
- data/test/helper.rb +128 -0
- data/test/search_classes/amazon.rb +6 -0
- data/test/search_classes/ebay.rb +6 -0
- data/test/search_classes/google.rb +6 -0
- data/test/search_classes/local.rb +6 -0
- data/test/test_awesome_search.rb +66 -0
- data/test/test_multiple.rb +24 -0
- data/test/test_multiple_filters.rb +31 -0
- data/test/test_multiple_locales.rb +24 -0
- data/test/test_multiple_types.rb +42 -0
- metadata +110 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Peter H. Boling (pboling on github)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
= Awesome Search
|
2
|
+
|
3
|
+
* A helpful library to make searching more organized in the controller and views.
|
4
|
+
* Using this library will force you to write a class for each kind of search you want to use.
|
5
|
+
* It has features that allow easy configuration of searches tailored to work with rsolr.
|
6
|
+
|
7
|
+
== Usage
|
8
|
+
|
9
|
+
See tests.
|
10
|
+
|
11
|
+
AwesomeSearch.results_for_type_and_locale(":local :text this is a test", ":upc", ":ebay")
|
12
|
+
|
13
|
+
== Configuration
|
14
|
+
|
15
|
+
These are the settings used by the test suite. Configure separately for each search class you create,
|
16
|
+
or all at once for AwesomeSearch.
|
17
|
+
|
18
|
+
AwesomeSearch.configure_search_locales do |config|
|
19
|
+
config[:search_locales_to_classes] =
|
20
|
+
{ ":local" => "SearchLocal",
|
21
|
+
":amazon" => "SearchAmazon",
|
22
|
+
":google" => "SearchGoogle",
|
23
|
+
":ebay" => "SearchEbay" },
|
24
|
+
config[:search_locales_to_locale_modifiers] =
|
25
|
+
{
|
26
|
+
":local" =>
|
27
|
+
[ ":local" ],
|
28
|
+
":amazon" =>
|
29
|
+
[ ":amazon",
|
30
|
+
":amzn",
|
31
|
+
":amz",
|
32
|
+
":am"],
|
33
|
+
":google" =>
|
34
|
+
[ ":google",
|
35
|
+
":goog",
|
36
|
+
":goo",
|
37
|
+
":go"],
|
38
|
+
":ebay" =>
|
39
|
+
[ ":ebay",
|
40
|
+
":eby",
|
41
|
+
":eb"]
|
42
|
+
},
|
43
|
+
config[:locale_modifiers_to_search_locales] =
|
44
|
+
{
|
45
|
+
":local" => ":local",
|
46
|
+
":amazon" => ":amazon",
|
47
|
+
":amz" => ":amazon",
|
48
|
+
":amzn" => ":amazon",
|
49
|
+
":am" => ":amazon",
|
50
|
+
":google" => ":google",
|
51
|
+
":goog" => ":google",
|
52
|
+
":goo" => ":google",
|
53
|
+
":go" => ":google",
|
54
|
+
":ebay" => ":ebay",
|
55
|
+
":eby" => ":ebay",
|
56
|
+
":eb" => ":ebay"
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
AwesomeSearch.configure_search_types do |config|
|
61
|
+
config[:search_types_to_type_modifiers] =
|
62
|
+
{
|
63
|
+
":isbn" => ":isbn",
|
64
|
+
":sku" => ":sku",
|
65
|
+
":upc" => ":upc",
|
66
|
+
":asin" => ":asin",
|
67
|
+
":id" => ":dbid",
|
68
|
+
":text" => ":text"
|
69
|
+
},
|
70
|
+
# When using observer, how long should we wait before sending out search queries?
|
71
|
+
config[:search_type_inceptions] =
|
72
|
+
{
|
73
|
+
":isbn" => 10,
|
74
|
+
":sku" => 8,
|
75
|
+
":upc" => 10,
|
76
|
+
":asin" => 10,
|
77
|
+
":id" => 1,
|
78
|
+
":text" => 4
|
79
|
+
},
|
80
|
+
config[:search_type_regexes] =
|
81
|
+
{
|
82
|
+
":isbn" => /\d{10}$|^\d{13}/, #match 10 or 13 digits for isbn
|
83
|
+
":sku" => /[0-9a-zA-Z\-]+/, #match any alphanumeric
|
84
|
+
":upc" => /\d{10}$|^\d{12}/,
|
85
|
+
":asin" => /\w{10}/,
|
86
|
+
":id" => /\d+/,
|
87
|
+
":text" => /\w{4}/
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
Create subclasses like this:
|
92
|
+
|
93
|
+
#1. inherit from SuperSearch (which inherits from AwesomeSearch)
|
94
|
+
class SearchAmazon < SuperSearch
|
95
|
+
#2. Define a method called get_results
|
96
|
+
def get_results
|
97
|
+
#3. Always return nil unless super, as super's get_results will ensure the search is valid
|
98
|
+
return nil unless super
|
99
|
+
#4. Here is where you would do actual searching. Write other methods and call them if need be or call methods in other classes, etc.
|
100
|
+
# You need to set the attribute 'found' to contain the search result(s).
|
101
|
+
# found is set to [] in the super, so you can iterate and do << with it,
|
102
|
+
# or set it to whatever you need it to be
|
103
|
+
self.found = Model.find(stuff) if stuff
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
== Note on Patches/Pull Requests
|
110
|
+
|
111
|
+
* Fork the project.
|
112
|
+
* Make your feature addition or bug fix.
|
113
|
+
* Add tests for it. This is important so I don't break it in a
|
114
|
+
future version unintentionally.
|
115
|
+
* Commit, do not mess with rakefile, version, or history.
|
116
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
117
|
+
* Send me a pull request. Bonus points for topic branches.
|
118
|
+
|
119
|
+
== Copyright
|
120
|
+
|
121
|
+
Copyright (c) 2008-10 Peter H. Boling, released under the MIT license. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "awesome_search"
|
8
|
+
gem.summary = %Q{Organize complicated search results}
|
9
|
+
gem.description = %Q{Organize complicated search results}
|
10
|
+
gem.email = "peter.boling@peterboling.com"
|
11
|
+
gem.homepage = "http://github.com/pboling/awesome_search"
|
12
|
+
gem.authors = ["pboling"]
|
13
|
+
gem.add_development_dependency "shoulda", ">= 0"
|
14
|
+
gem.add_runtime_dependency "activesupport", ">= 2.1"
|
15
|
+
gem.files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc",
|
18
|
+
"Rakefile",
|
19
|
+
"VERSION",
|
20
|
+
"awesome_search.gemspec",
|
21
|
+
"init.rb",
|
22
|
+
"lib/awesome/definitions/bits.rb",
|
23
|
+
"lib/awesome/definitions/filters.rb",
|
24
|
+
"lib/awesome/definitions/locales.rb",
|
25
|
+
"lib/awesome/definitions/types.rb",
|
26
|
+
"lib/awesome/search.rb",
|
27
|
+
"lib/awesome/super_search.rb",
|
28
|
+
"lib/awesome/triage.rb",
|
29
|
+
"lib/awesome_search.rb",
|
30
|
+
"rails/init.rb",
|
31
|
+
"init.rb"
|
32
|
+
]
|
33
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
34
|
+
end
|
35
|
+
Jeweler::GemcutterTasks.new
|
36
|
+
rescue LoadError
|
37
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
38
|
+
end
|
39
|
+
|
40
|
+
require 'rake/testtask'
|
41
|
+
Rake::TestTask.new(:test) do |test|
|
42
|
+
test.libs << 'lib' << 'test'
|
43
|
+
test.pattern = 'test/**/test_*.rb'
|
44
|
+
test.verbose = true
|
45
|
+
end
|
46
|
+
|
47
|
+
begin
|
48
|
+
require 'rcov/rcovtask'
|
49
|
+
Rcov::RcovTask.new do |test|
|
50
|
+
test.libs << 'test'
|
51
|
+
test.pattern = 'test/**/test_*.rb'
|
52
|
+
test.verbose = true
|
53
|
+
end
|
54
|
+
rescue LoadError
|
55
|
+
task :rcov do
|
56
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
task :test => :check_dependencies
|
61
|
+
|
62
|
+
task :default => :test
|
63
|
+
|
64
|
+
require 'rake/rdoctask'
|
65
|
+
Rake::RDocTask.new do |rdoc|
|
66
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
67
|
+
|
68
|
+
rdoc.rdoc_dir = 'rdoc'
|
69
|
+
rdoc.title = "awesome_search #{version}"
|
70
|
+
rdoc.rdoc_files.include('README*')
|
71
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
72
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.1
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{awesome_search}
|
8
|
+
s.version = "1.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["pboling"]
|
12
|
+
s.date = %q{2010-04-29}
|
13
|
+
s.description = %q{Organize complicated search results}
|
14
|
+
s.email = %q{peter.boling@peterboling.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"LICENSE",
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"awesome_search.gemspec",
|
25
|
+
"init.rb",
|
26
|
+
"lib/awesome/definitions/bits.rb",
|
27
|
+
"lib/awesome/definitions/filters.rb",
|
28
|
+
"lib/awesome/definitions/locales.rb",
|
29
|
+
"lib/awesome/definitions/types.rb",
|
30
|
+
"lib/awesome/search.rb",
|
31
|
+
"lib/awesome/super_search.rb",
|
32
|
+
"lib/awesome/triage.rb",
|
33
|
+
"lib/awesome_search.rb",
|
34
|
+
"rails/init.rb"
|
35
|
+
]
|
36
|
+
s.homepage = %q{http://github.com/pboling/awesome_search}
|
37
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.rubygems_version = %q{1.3.6}
|
40
|
+
s.summary = %q{Organize complicated search results}
|
41
|
+
s.test_files = [
|
42
|
+
"test/helper.rb",
|
43
|
+
"test/search_classes/amazon.rb",
|
44
|
+
"test/search_classes/ebay.rb",
|
45
|
+
"test/search_classes/google.rb",
|
46
|
+
"test/search_classes/local.rb",
|
47
|
+
"test/test_awesome_search.rb",
|
48
|
+
"test/test_multiple.rb",
|
49
|
+
"test/test_multiple_filters.rb",
|
50
|
+
"test/test_multiple_locales.rb",
|
51
|
+
"test/test_multiple_types.rb"
|
52
|
+
]
|
53
|
+
|
54
|
+
if s.respond_to? :specification_version then
|
55
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
56
|
+
s.specification_version = 3
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
59
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
60
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 2.1"])
|
61
|
+
else
|
62
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
63
|
+
s.add_dependency(%q<activesupport>, [">= 2.1"])
|
64
|
+
end
|
65
|
+
else
|
66
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
67
|
+
s.add_dependency(%q<activesupport>, [">= 2.1"])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/rails/init"
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Awesome
|
2
|
+
module Definitions
|
3
|
+
module Bits
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
def get_class(name)
|
12
|
+
const_get(name) unless name.blank?
|
13
|
+
end
|
14
|
+
|
15
|
+
def modifier_regex_from_array(arr, whitespace = false)
|
16
|
+
self.modifier_regex(self.array_to_middle_regex(arr, whitespace))
|
17
|
+
end
|
18
|
+
|
19
|
+
def array_to_middle_regex(arr, whitespace = false)
|
20
|
+
return '' if arr.empty?
|
21
|
+
arr = whitespace ?
|
22
|
+
arr.map {|x| '(\s*' + x + '\s*)'} :
|
23
|
+
arr.map {|x| '(' + x + ')'}
|
24
|
+
arr.join('|')
|
25
|
+
end
|
26
|
+
|
27
|
+
def modifier_regex(middle)
|
28
|
+
Regexp.new(middle)
|
29
|
+
end
|
30
|
+
|
31
|
+
# In dealing with symbols and strings and params from requests
|
32
|
+
# comparisons can fail even when we want them to pass.
|
33
|
+
# This prevents those unwanted failures
|
34
|
+
# We will compare strings of this format ":ebay"
|
35
|
+
def symring_equalizer(one, two)
|
36
|
+
return self.make_symring(one) == self.make_symring(two)
|
37
|
+
end
|
38
|
+
|
39
|
+
def make_symring(var)
|
40
|
+
if var.is_a?(Symbol)
|
41
|
+
return ":#{var}"
|
42
|
+
elsif var.is_a?(String)
|
43
|
+
var.include?(':') ? var.strip : ":#{var.strip}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def unmake_symring(var)
|
48
|
+
return "#{var}".delete(':')
|
49
|
+
end
|
50
|
+
|
51
|
+
#def modifier_regex_from_arrays(arr, whitespace = false)
|
52
|
+
# self.modifier_regex(array_of_arrays_to_middle_regex(arr, whitespace))
|
53
|
+
#end
|
54
|
+
|
55
|
+
#Returns a string of a partial regex
|
56
|
+
#def array_of_arrays_to_middle_regex(arr, whitespace = false)
|
57
|
+
# arr = arr.map do |array|
|
58
|
+
# "(" + self.array_to_middle_regex(array, whitespace) + ")"
|
59
|
+
# end
|
60
|
+
# arr.join('|')
|
61
|
+
#end
|
62
|
+
|
63
|
+
#def looped_array(a)
|
64
|
+
# b = []
|
65
|
+
# a.length.times do
|
66
|
+
# b << Array.new(a.insert(0,a.pop))
|
67
|
+
# end
|
68
|
+
# b
|
69
|
+
#end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Awesome
|
2
|
+
module Definitions
|
3
|
+
module Filters
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
base.cattr_accessor :search_filters
|
8
|
+
base.cattr_accessor :verbose_filters
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def search_filters_enabled
|
14
|
+
self.search_filter_keys(false)
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_class_for_filter(filter)
|
18
|
+
self.get_class(self.search_filters[:search_filters_to_classes][filter])
|
19
|
+
end
|
20
|
+
|
21
|
+
def search_filter_keys(symring = true)
|
22
|
+
self.search_filters[:search_filters_to_filter_modifiers].map {|k,v| symring ? k : self.unmake_symring(k)}
|
23
|
+
end
|
24
|
+
|
25
|
+
def search_filter_modifiers(symring = true)
|
26
|
+
# Needs to be flattened because the values are arrays
|
27
|
+
self.search_filters[:search_filters_to_filter_modifiers].map {|k,v| symring ? v : self.unmake_symring(v)}.flatten
|
28
|
+
end
|
29
|
+
|
30
|
+
# filter param is an array of filters
|
31
|
+
def valid_filter_modifiers(anytext, filter)
|
32
|
+
# Weed out invalid filter requests
|
33
|
+
puts "checking valid_filter_modifiers: #{anytext}, filter: #{filter.inspect}" if self.verbose_filters
|
34
|
+
# We do not make_symring for two reasons:
|
35
|
+
# 1. people will use whatever kind of filter value they need, and ruby can compare it.
|
36
|
+
# 2. the filter param is an array
|
37
|
+
# #filter = self.make_symring(filter)
|
38
|
+
# Weed out invalid filter requests
|
39
|
+
allowed = (self.search_filter_keys & filter)
|
40
|
+
return false if !filter.empty? && allowed.empty?
|
41
|
+
valid_filter_mods = self.get_filter_modifiers(anytext, allowed)
|
42
|
+
valid_search_filters = valid_filter_mods.map do |fmod|
|
43
|
+
puts "filter mod #{fmod.inspect} => #{self.search_filters[:filter_modifiers_to_search_filters][fmod]}" if self.verbose_filters
|
44
|
+
self.search_filters[:filter_modifiers_to_search_filters][fmod]
|
45
|
+
end.compact
|
46
|
+
puts "valid_filter_modifiers: #{valid_search_filters.inspect}" if self.verbose_filters
|
47
|
+
return valid_search_filters
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_filter_modifiers(anytext, filter = nil)
|
51
|
+
mods = anytext.scan(self.search_filter_modifiers_regex(false)).flatten.compact
|
52
|
+
#If no filter mods are in the search string then the filter requested is valid so we pretend it was requested as a modifier
|
53
|
+
mods = !filter.blank? && mods.empty? ? [self.make_symring(filter)] : mods
|
54
|
+
#mods = (self.search_filter_modifiers & mods) | filter
|
55
|
+
puts "get_filter_modifiers #{mods.reject {|x| x == ''}.inspect}" if self.verbose_filters
|
56
|
+
mods.reject {|x| x == ''}
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_search_filter_from_modifier(mod)
|
60
|
+
self.search_filters[:filter_modifiers_to_search_filters][mod]
|
61
|
+
end
|
62
|
+
|
63
|
+
def search_filter_modifiers_regex(whitespace = false)
|
64
|
+
self.modifier_regex_from_array(self.search_filter_modifiers, whitespace)
|
65
|
+
end
|
66
|
+
end # end of ClassMethods
|
67
|
+
|
68
|
+
#INSTANCE METHODS
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Awesome
|
2
|
+
module Definitions
|
3
|
+
module Locales
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
base.cattr_accessor :search_locales
|
8
|
+
base.cattr_accessor :verbose_locales
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def stopwords_for_locale(locale)
|
14
|
+
self.search_locales[:search_locales_to_stopwords][locale]
|
15
|
+
end
|
16
|
+
|
17
|
+
def search_locales_enabled
|
18
|
+
self.search_locale_keys(false)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_class_for_locale(locale)
|
22
|
+
self.get_class(self.search_locales[:search_locales_to_classes][locale])
|
23
|
+
end
|
24
|
+
|
25
|
+
def search_locale_keys(symring = true)
|
26
|
+
self.search_locales[:search_locales_to_locale_modifiers].map {|k,v| symring ? k : self.unmake_symring(k)}
|
27
|
+
end
|
28
|
+
|
29
|
+
def search_locale_modifiers(symring = true)
|
30
|
+
# Needs to be flattened because the values are arrays
|
31
|
+
self.search_locales[:search_locales_to_locale_modifiers].map {|k,v| symring ? v : self.unmake_symring(v)}.flatten
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid_locale_modifiers(anytext, locale)
|
35
|
+
# Weed out invalid locale requests
|
36
|
+
puts "checking valid_locale_modifiers: #{anytext}, locale: #{locale.inspect}" if self.verbose_locales
|
37
|
+
locale = self.make_symring(locale)
|
38
|
+
return false unless self.search_locale_keys.include?(locale)
|
39
|
+
mods = self.get_locale_modifiers(anytext, locale)
|
40
|
+
valid_mods = mods.select do |mod|
|
41
|
+
puts "locale mod #{mod.inspect} => #{self.get_search_locale_from_modifier(mod)} == #{locale.inspect}" if self.verbose_locales
|
42
|
+
self.symring_equalizer(self.get_search_locale_from_modifier(mod), locale)
|
43
|
+
end
|
44
|
+
puts "valid_locale_modifiers: #{valid_mods.inspect}" if self.verbose_locales
|
45
|
+
return valid_mods
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_locale_modifiers(anytext, locale = nil)
|
49
|
+
mods = anytext.scan(self.search_locale_modifiers_regex(false)).flatten.compact
|
50
|
+
#If no locale mods are in the search string then the locale requested is valid so we pretend it was requested as a modifier
|
51
|
+
mods = !locale.blank? && mods.empty? ? [self.make_symring(locale)] : mods
|
52
|
+
puts "get_locale_modifiers: #{mods.reject {|x| x == ''}.inspect}" if self.verbose_locales
|
53
|
+
mods.reject {|x| x == ''}
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_search_locale_from_modifier(mod)
|
57
|
+
self.search_locales[:locale_modifiers_to_search_locales][mod]
|
58
|
+
end
|
59
|
+
|
60
|
+
def search_locale_modifiers_regex(whitespace = false)
|
61
|
+
self.modifier_regex_from_array(self.search_locale_modifiers, whitespace)
|
62
|
+
end
|
63
|
+
end # end of ClassMethods
|
64
|
+
|
65
|
+
#INSTANCE METHODS
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Awesome
|
2
|
+
module Definitions
|
3
|
+
module Types
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
base.cattr_accessor :search_types
|
7
|
+
base.cattr_accessor :verbose_types
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
def search_types_enabled
|
13
|
+
self.search_type_keys(false) - []
|
14
|
+
end
|
15
|
+
|
16
|
+
def search_type_keys(symring = true)
|
17
|
+
self.search_types[:search_types_to_type_modifiers].map {|k,v| symring ? k : self.unmake_symring(k)}
|
18
|
+
end
|
19
|
+
|
20
|
+
def search_type_modifiers(symring = true)
|
21
|
+
self.search_types[:search_types_to_type_modifiers].map {|k,v| symring ? v : self.unmake_symring(v)}
|
22
|
+
end
|
23
|
+
|
24
|
+
def type_modifiers_to_search_types
|
25
|
+
self.search_types[:search_types_to_type_modifiers].invert
|
26
|
+
end
|
27
|
+
|
28
|
+
# match a regex for the type
|
29
|
+
def match_types
|
30
|
+
return self.search_types[:search_type_regexes].map do |key,value|
|
31
|
+
self.search_query.match(value) ? key : nil
|
32
|
+
end.compact
|
33
|
+
end
|
34
|
+
|
35
|
+
# type param might be an array of types
|
36
|
+
def valid_type_modifiers(anytext, type, multiple_types_as_one = false)
|
37
|
+
puts "checking valid_type_modifiers: #{anytext}, type: #{type.inspect}, multiple_types_as_one: #{multiple_types_as_one}" if self.verbose_types
|
38
|
+
# Weed out invalid type requests
|
39
|
+
if multiple_types_as_one
|
40
|
+
#when using multiple types as one the keys are the modifiers, and the values are the search types
|
41
|
+
allowed = self.search_type_keys & type
|
42
|
+
valid_mods = allowed.map do |mod|
|
43
|
+
self.get_search_type_from_modifier(mod)
|
44
|
+
end.flatten.compact
|
45
|
+
else
|
46
|
+
#when NOT using multiple types as one the keys are the types, and the values are the modifiers
|
47
|
+
type = self.make_symring(type)
|
48
|
+
return [] unless self.search_type_keys.include?(type)
|
49
|
+
mods = self.get_type_modifiers(anytext, type)
|
50
|
+
searchie = self.type_modifiers_to_search_types
|
51
|
+
matchie = self.match_types
|
52
|
+
valid_mods = mods.select do |mod|
|
53
|
+
indy = matchie.index(searchie[mod])
|
54
|
+
puts "type mod #{mod.inspect} => #{searchie[mod].inspect} == #{indy ? matchie[indy].inspect : "nil"} == #{type.inspect}" if self.verbose_types
|
55
|
+
!indy.nil? &&
|
56
|
+
!matchie.nil? &&
|
57
|
+
!searchie.nil? &&
|
58
|
+
self.symring_equalizer(searchie[mod], type) && self.symring_equalizer(matchie[indy], type)
|
59
|
+
# (multiple_types_as_one ? type.include?(searchie[mod]) : self.symring_equalizer(searchie[mod], type)) &&
|
60
|
+
# (multiple_types_as_one ? type.include?(matchie[indy]) : self.symring_equalizer(matchie[indy], type))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
puts "valid_type_modifiers: #{valid_mods.inspect}" if self.verbose_types
|
64
|
+
return valid_mods
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_type_modifiers(anytext, type = nil, multiple_types_as_one = false)
|
68
|
+
mods = anytext.scan(self.search_type_modifiers_regex(false, multiple_types_as_one)).flatten.compact.reject {|x| x == ''}
|
69
|
+
#If no type mods are in the search string then the type requested is valid so we pretend it was requested as a modifier
|
70
|
+
mods = mods.empty? ? multiple_types_as_one ? type : [self.search_types[:search_types_to_type_modifiers][self.make_symring(type)]] : mods
|
71
|
+
puts "get_type_modifiers: #{mods.inspect}" if self.verbose_types
|
72
|
+
mods
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_search_type_from_modifier(mod)
|
76
|
+
self.search_types[:search_types_to_type_modifiers][mod]
|
77
|
+
end
|
78
|
+
|
79
|
+
def search_type_modifiers_regex(whitespace = false, multiple_types_as_one = false)
|
80
|
+
#return self.modifier_regex_from_arrays(self.looped_array(self.search_type_modifiers), whitespace)
|
81
|
+
self.modifier_regex_from_array(multiple_types_as_one ? self.search_type_keys : self.search_type_modifiers, whitespace)
|
82
|
+
end
|
83
|
+
|
84
|
+
end # end of ClassMethods
|
85
|
+
|
86
|
+
#INSTANCE METHODS
|
87
|
+
def valid_search_type_inception?
|
88
|
+
self.class.search_types[:search_type_inceptions][self.search_type] <= self.search_query.length
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|