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