quick_search-core 0.0.1.test
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +168 -0
- data/Rakefile +6 -0
- data/app/assets/images/quick_search/askus.gif +0 -0
- data/app/assets/images/quick_search/favicon.ico +0 -0
- data/app/assets/images/quick_search/greybox.png +0 -0
- data/app/assets/images/quick_search/homescreen-icon-64x64.png +0 -0
- data/app/assets/images/quick_search/ncsu-library-logo-white.png +0 -0
- data/app/assets/javascripts/quick_search/appstats.js +8 -0
- data/app/assets/javascripts/quick_search/event_tracking.js.erb +257 -0
- data/app/assets/javascripts/quick_search/google_analytics.js.erb +8 -0
- data/app/assets/javascripts/quick_search/opensearch.js +2 -0
- data/app/assets/javascripts/quick_search/pages.js.coffee +3 -0
- data/app/assets/javascripts/quick_search/quicksearch.js +33 -0
- data/app/assets/javascripts/quick_search/realtime.js.erb +12 -0
- data/app/assets/javascripts/quick_search/search.js +3 -0
- data/app/assets/javascripts/quick_search/xhr_search.js +82 -0
- data/app/assets/javascripts/quick_search.js.erb +20 -0
- data/app/assets/stylesheets/foundation_and_overrides.scss +1327 -0
- data/app/assets/stylesheets/quick_search/appstats.css.scss +7 -0
- data/app/assets/stylesheets/quick_search/opensearch.css.scss +3 -0
- data/app/assets/stylesheets/quick_search/pages.css.scss +3 -0
- data/app/assets/stylesheets/quick_search/quick_search.css.scss +248 -0
- data/app/assets/stylesheets/quick_search/search.css.scss +3 -0
- data/app/assets/stylesheets/quick_search.css.scss.erb +7 -0
- data/app/controllers/concerns/quick_search/auth.rb +22 -0
- data/app/controllers/concerns/quick_search/doi_trap.rb +43 -0
- data/app/controllers/concerns/quick_search/encode_utf8.rb +12 -0
- data/app/controllers/concerns/quick_search/on_campus.rb +43 -0
- data/app/controllers/concerns/quick_search/query_filter.rb +25 -0
- data/app/controllers/concerns/quick_search/query_parser.rb +54 -0
- data/app/controllers/concerns/quick_search/searcher_concern.rb +101 -0
- data/app/controllers/concerns/quick_search/searcher_config.rb +16 -0
- data/app/controllers/quick_search/application_controller.rb +7 -0
- data/app/controllers/quick_search/appstats_controller.rb +210 -0
- data/app/controllers/quick_search/opensearch_controller.rb +9 -0
- data/app/controllers/quick_search/pages_controller.rb +18 -0
- data/app/controllers/quick_search/search_controller.rb +250 -0
- data/app/helpers/quick_search/application_helper.rb +68 -0
- data/app/helpers/quick_search/appstats_helper.rb +2 -0
- data/app/helpers/quick_search/opensearch_helper.rb +2 -0
- data/app/helpers/quick_search/pages_helper.rb +2 -0
- data/app/helpers/quick_search/search_helper.rb +2 -0
- data/app/models/event.rb +2 -0
- data/app/models/search.rb +11 -0
- data/app/searchers/quick_search/best_bets_searcher.rb +102 -0
- data/app/searchers/quick_search/searcher.rb +43 -0
- data/app/views/layouts/quick_search/_best_bets.html.erb +18 -0
- data/app/views/layouts/quick_search/_common_searches.html.erb +15 -0
- data/app/views/layouts/quick_search/_found_types.html.erb +13 -0
- data/app/views/layouts/quick_search/_google_analytics.html.erb +24 -0
- data/app/views/layouts/quick_search/_more_options.html.erb +10 -0
- data/app/views/layouts/quick_search/_page_title.html.erb +8 -0
- data/app/views/layouts/quick_search/_related_topics.html.erb +8 -0
- data/app/views/layouts/quick_search/_search_form.html.erb +19 -0
- data/app/views/layouts/quick_search/_spelling_suggestion.html.erb +13 -0
- data/app/views/layouts/quick_search/_topic_snippet.html.erb +5 -0
- data/app/views/layouts/quick_search/application.html.erb +40 -0
- data/app/views/quick_search/appstats/_click_count_table.html.erb +23 -0
- data/app/views/quick_search/appstats/_datatables.html.erb +12 -0
- data/app/views/quick_search/appstats/_date_range.html.erb +15 -0
- data/app/views/quick_search/appstats/_menu.html.erb +16 -0
- data/app/views/quick_search/appstats/_top_spot_report_table.html.erb +33 -0
- data/app/views/quick_search/appstats/clicks_overview.html.erb +20 -0
- data/app/views/quick_search/appstats/index.html.erb +31 -0
- data/app/views/quick_search/appstats/module_click_detail.html.erb +32 -0
- data/app/views/quick_search/appstats/realtime.html.erb +15 -0
- data/app/views/quick_search/appstats/top_searches.html.erb +38 -0
- data/app/views/quick_search/appstats/top_spot.html.erb +14 -0
- data/app/views/quick_search/appstats/top_spot_detail.html.erb +35 -0
- data/app/views/quick_search/kaminari/_first_page.html.erb +12 -0
- data/app/views/quick_search/kaminari/_gap.html.erb +11 -0
- data/app/views/quick_search/kaminari/_last_page.html.erb +12 -0
- data/app/views/quick_search/kaminari/_next_page.html.erb +12 -0
- data/app/views/quick_search/kaminari/_page.html.erb +13 -0
- data/app/views/quick_search/kaminari/_paginator.html.erb +25 -0
- data/app/views/quick_search/kaminari/_prev_page.html.erb +11 -0
- data/app/views/quick_search/opensearch/opensearch.xml.builder +11 -0
- data/app/views/quick_search/pages/about.html.erb +9 -0
- data/app/views/quick_search/pages/home.html.erb +6 -0
- data/app/views/quick_search/pages/realtime.html.erb +15 -0
- data/app/views/quick_search/search/_citation.html.erb +18 -0
- data/app/views/quick_search/search/_module.html.erb +37 -0
- data/app/views/quick_search/search/_module_with_paging.html.erb +14 -0
- data/app/views/quick_search/search/_no_results.html.erb +11 -0
- data/app/views/quick_search/search/_result.html.erb +17 -0
- data/app/views/quick_search/search/_result_details.html.erb +45 -0
- data/app/views/quick_search/search/_result_no_thumbnail.html.erb +3 -0
- data/app/views/quick_search/search/_result_title.html.erb +4 -0
- data/app/views/quick_search/search/_result_with_thumbnail.html.erb +21 -0
- data/app/views/quick_search/search/_search_error.html.erb +9 -0
- data/app/views/quick_search/search/_see_all.html.erb +11 -0
- data/app/views/quick_search/search/_xhr_response.html.erb +15 -0
- data/app/views/quick_search/search/_xhr_response.json.erb +14 -0
- data/app/views/quick_search/search/_xhr_response_with_paging.html.erb +1 -0
- data/app/views/quick_search/search/index.html.erb +100 -0
- data/config/application.rb +25 -0
- data/config/best_bets.yml +86 -0
- data/config/boot.rb +4 -0
- data/config/database.yml.example +31 -0
- data/config/locales/en.yml +30 -0
- data/config/quicksearch_config.yml.example +69 -0
- data/config/routes.rb +81 -0
- data/db/migrate/20140130202859_create_events.rb +11 -0
- data/db/migrate/20140130202944_create_searches.rb +9 -0
- data/db/migrate/20140225145441_add_page_to_searches.rb +5 -0
- data/db/schema.rb +31 -0
- data/db/seeds.rb +7 -0
- data/lib/benchmark_logger.rb +2 -0
- data/lib/capistrano/tasks/access_check.cap +10 -0
- data/lib/generators/quick_search/install_generator.rb +49 -0
- data/lib/generators/quick_search/templates/kaminari.rb +5 -0
- data/lib/generators/quick_search/templates/post_install.txt +8 -0
- data/lib/generators/quick_search/templates/quick_search_config.yml +58 -0
- data/lib/quick_search/engine.rb +16 -0
- data/lib/quick_search/version.rb +3 -0
- data/lib/quick_search.rb +12 -0
- data/lib/tasks/best_bets.rake +29 -0
- data/test/controllers/appstats_controller_test.rb +7 -0
- data/test/controllers/concerns/doi_trap_test.rb +19 -0
- data/test/controllers/concerns/on_campus_test.rb +19 -0
- data/test/controllers/concerns/query_parser_test.rb +47 -0
- data/test/controllers/opensearch_controller_test.rb +13 -0
- data/test/controllers/pages_controller_test.rb +7 -0
- data/test/controllers/search_controller_test.rb +15 -0
- data/test/fixtures/events.yml +11 -0
- data/test/fixtures/searches.yml +7 -0
- data/test/helpers/appstats_helper_test.rb +4 -0
- data/test/helpers/opensearch_helper_test.rb +4 -0
- data/test/helpers/pages_helper_test.rb +4 -0
- data/test/helpers/search_helper_test.rb +4 -0
- data/test/integration/catalog_search_test.rb +8 -0
- data/test/integration/google_analytics_test.rb +23 -0
- data/test/integration/landing_page_test.rb +8 -0
- data/test/integration/searching_test.rb +40 -0
- data/test/integration/smart_subjects_test.rb +8 -0
- data/test/integration/website_search_test.rb +8 -0
- data/test/models/event_test.rb +7 -0
- data/test/models/search_test.rb +7 -0
- data/test/searcher/best_bets_test.rb +35 -0
- data/test/searcher/catalog_test.rb +35 -0
- data/test/searcher/ematrix_database_test.rb +27 -0
- data/test/searcher/ematrix_journal_test.rb +27 -0
- data/test/searcher/faq_test.rb +27 -0
- data/test/searcher/smart_subjects_test.rb +27 -0
- data/test/searcher/summon_test.rb +13 -0
- data/test/searcher/website_test.rb +34 -0
- data/test/support/vcr_test.rb +40 -0
- data/test/test_helper.rb +42 -0
- metadata +366 -0
@@ -0,0 +1,248 @@
|
|
1
|
+
@mixin text-badge {
|
2
|
+
padding: 1px 5px 2px 5px;
|
3
|
+
border-radius: 2px;
|
4
|
+
color: #FFF;
|
5
|
+
}
|
6
|
+
|
7
|
+
//element overrides
|
8
|
+
#content {
|
9
|
+
#main-content {
|
10
|
+
#quicksearch {
|
11
|
+
|
12
|
+
.twitter-typeahead {
|
13
|
+
width: 100%;
|
14
|
+
|
15
|
+
img {
|
16
|
+
max-width: 79.578125px;
|
17
|
+
}
|
18
|
+
.space-container {
|
19
|
+
max-width: 438.3125px;
|
20
|
+
}
|
21
|
+
|
22
|
+
.bestbet-container {
|
23
|
+
padding: 0;
|
24
|
+
}
|
25
|
+
|
26
|
+
}
|
27
|
+
|
28
|
+
h3 {
|
29
|
+
padding-top: 0;
|
30
|
+
font-weight: normal;
|
31
|
+
}
|
32
|
+
|
33
|
+
ol, ul {
|
34
|
+
margin-left: 0;
|
35
|
+
}
|
36
|
+
|
37
|
+
li {
|
38
|
+
list-style-type: none;
|
39
|
+
}
|
40
|
+
|
41
|
+
em {
|
42
|
+
font-style: normal;
|
43
|
+
font-weight: bold;
|
44
|
+
}
|
45
|
+
|
46
|
+
#website {
|
47
|
+
margin-bottom: 2.5em;
|
48
|
+
}
|
49
|
+
|
50
|
+
// class overrides
|
51
|
+
|
52
|
+
.prefix.button {
|
53
|
+
height: 2.3rem
|
54
|
+
}
|
55
|
+
|
56
|
+
@media only screen and (max-width: 766px) {
|
57
|
+
.prefix.button {
|
58
|
+
height: 2.76rem
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
input[type="text"] {
|
63
|
+
-webkit-appearance: none;
|
64
|
+
border-radius: 0;
|
65
|
+
font-size: 1rem;
|
66
|
+
}
|
67
|
+
|
68
|
+
input[type="search"] {
|
69
|
+
margin: 0;
|
70
|
+
}
|
71
|
+
|
72
|
+
// custom classes
|
73
|
+
|
74
|
+
.about {
|
75
|
+
float: right;
|
76
|
+
}
|
77
|
+
|
78
|
+
.result-types {
|
79
|
+
margin: 10px 0 0 0;
|
80
|
+
li {
|
81
|
+
margin: 0 20px 0 0;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
.trying_again {
|
86
|
+
padding-bottom: 20px;
|
87
|
+
}
|
88
|
+
|
89
|
+
.clear-search-box {
|
90
|
+
display: none;
|
91
|
+
}
|
92
|
+
|
93
|
+
.title {
|
94
|
+
font-size: 1.25em;
|
95
|
+
margin-bottom:0;
|
96
|
+
margin-top: 1em;
|
97
|
+
}
|
98
|
+
|
99
|
+
.result {
|
100
|
+
p {
|
101
|
+
margin-bottom: 0;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
.see-all-results {
|
106
|
+
margin-bottom: 2.5em;
|
107
|
+
margin-top: 2em;
|
108
|
+
font-weight: bold;
|
109
|
+
}
|
110
|
+
|
111
|
+
.search-error-message {
|
112
|
+
margin-top: 1em
|
113
|
+
}
|
114
|
+
|
115
|
+
.with-thumbnail {
|
116
|
+
margin-bottom: 0.9em;
|
117
|
+
}
|
118
|
+
|
119
|
+
.no-thumbnail {
|
120
|
+
margin-bottom: 0.9em;
|
121
|
+
}
|
122
|
+
|
123
|
+
.link {
|
124
|
+
display: none;
|
125
|
+
word-break: break-word;
|
126
|
+
}
|
127
|
+
|
128
|
+
.query {
|
129
|
+
font-weight: bold;
|
130
|
+
word-break: break-word;
|
131
|
+
}
|
132
|
+
|
133
|
+
.display-link {
|
134
|
+
word-break: break-all;
|
135
|
+
}
|
136
|
+
|
137
|
+
.highlight {
|
138
|
+
@include text-badge;
|
139
|
+
background: #edb802;
|
140
|
+
@media only screen and (max-width: 640px) {
|
141
|
+
display: none;
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
.result-types-highlight {
|
146
|
+
@media only screen and (max-width: 640px) {
|
147
|
+
display: none;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
.available {
|
152
|
+
color: #090;
|
153
|
+
}
|
154
|
+
|
155
|
+
.unavailable {
|
156
|
+
color: #C00;
|
157
|
+
}
|
158
|
+
|
159
|
+
.section-description {
|
160
|
+
text-transform: none;
|
161
|
+
margin-top: 1em;
|
162
|
+
}
|
163
|
+
|
164
|
+
.side-bar {
|
165
|
+
span.total {
|
166
|
+
display: none;
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
.thumbnail {
|
171
|
+
border: 1px solid #555555;
|
172
|
+
}
|
173
|
+
|
174
|
+
.citation {
|
175
|
+
.publisher {
|
176
|
+
font-style: italic;
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
.date {
|
181
|
+
font-weight: normal;
|
182
|
+
}
|
183
|
+
|
184
|
+
.search-error-rescue {
|
185
|
+
display: none;
|
186
|
+
}
|
187
|
+
|
188
|
+
.website {
|
189
|
+
.link {
|
190
|
+
display: block;
|
191
|
+
color: #006621;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
|
195
|
+
.summon {
|
196
|
+
.description {
|
197
|
+
display: none;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
|
202
|
+
.faq {
|
203
|
+
.total {
|
204
|
+
display: none;
|
205
|
+
}
|
206
|
+
}
|
207
|
+
|
208
|
+
|
209
|
+
.related-topics {
|
210
|
+
ul {
|
211
|
+
column-count: 2;
|
212
|
+
-moz-column-count: 2; /* Firefox */
|
213
|
+
-webkit-column-count: 2; /* Safari and Chrome */
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
217
|
+
.journals-databases, .faq {
|
218
|
+
h3 {
|
219
|
+
font-size: 1.1em;
|
220
|
+
}
|
221
|
+
li {
|
222
|
+
margin-bottom: 0;
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
.appstats-show {
|
227
|
+
.total {
|
228
|
+
font-weight: bold;
|
229
|
+
}
|
230
|
+
}
|
231
|
+
}
|
232
|
+
}
|
233
|
+
}
|
234
|
+
|
235
|
+
|
236
|
+
// hide google analytics debug
|
237
|
+
|
238
|
+
#quicksearch-ga-debug {
|
239
|
+
display: none;
|
240
|
+
}
|
241
|
+
|
242
|
+
// .hidden {
|
243
|
+
// display: none;
|
244
|
+
// }
|
245
|
+
|
246
|
+
.feedback-form {
|
247
|
+
display: none;
|
248
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "digest/md5"
|
2
|
+
|
3
|
+
module QuickSearch::Auth
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
SALT01 = SecureRandom.hex(512)
|
7
|
+
SALT02 = SecureRandom.hex(512)
|
8
|
+
REALM = "Please enter the username and password to access this page"
|
9
|
+
USERS = {"#{QuickSearch::Engine::APP_CONFIG['user']}" => Digest::MD5.hexdigest(["#{QuickSearch::Engine::APP_CONFIG['user']}",REALM,"#{QuickSearch::Engine::APP_CONFIG['password']}"].join(":"))}
|
10
|
+
SALTY = SALT01 + Digest::MD5.hexdigest(["#{QuickSearch::Engine::APP_CONFIG['user']}",REALM,"#{QuickSearch::Engine::APP_CONFIG['password']}"].join(":")) + SALT02
|
11
|
+
|
12
|
+
def auth
|
13
|
+
authenticate_or_request_with_http_digest(REALM) do |username|
|
14
|
+
unless SALT01.blank? or SALT02.blank? or USERS[username].blank?
|
15
|
+
if SALT01 + USERS[username] + SALT02 == SALTY
|
16
|
+
USERS[username]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module QuickSearch::DoiTrap
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
include QuickSearch::EncodeUtf8
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def doi_trap
|
9
|
+
unless params_q_scrubbed.nil?
|
10
|
+
if is_a_doi?(doi_query)
|
11
|
+
Event.create(category: 'doi-trap', action: doi_query, label: '')
|
12
|
+
redirect_to doi_loaded_link
|
13
|
+
# Alternately insert a loaded link into the results interface
|
14
|
+
# @doi_loaded_link = loaded_link
|
15
|
+
# @doi_callout = "Searching for a DOI? Try this: "
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def is_a_doi?(query)
|
21
|
+
if doi_regex.match(query)
|
22
|
+
true
|
23
|
+
else
|
24
|
+
false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def doi_regex
|
29
|
+
/^(?:(?:doi:?\s*|(?:http:\/\/)?(?:dx\.)?(?:doi\.org)?\/))?(10(?:\.\d+){1,2}\/\S+)$/i
|
30
|
+
end
|
31
|
+
|
32
|
+
def doi_loaded_link
|
33
|
+
QuickSearch::Engine::APP_CONFIG['doi_loaded_link'] + CGI.escape(doi_regex.match(doi_query)[1])
|
34
|
+
end
|
35
|
+
|
36
|
+
def doi_query
|
37
|
+
query = params_q_scrubbed
|
38
|
+
query.strip!
|
39
|
+
query.squish!
|
40
|
+
query
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module QuickSearch::OnCampus
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
# Search for "Nucleation and growth mechanism of ferroelectric domain wall motion"
|
7
|
+
# To test this. Result should not show up in Summon results off campus.
|
8
|
+
|
9
|
+
### WHY THIS IS HERE ###
|
10
|
+
# There is a subset of Summon results that cannot be shown unless a person is
|
11
|
+
# on campus or authenticated. So that we can show all results to people
|
12
|
+
# searching QuickSearch from on campus we're checking IP addresses. If the IP is a
|
13
|
+
# known campus IP we set the s.role=authenticated parameter in the Summon API request.
|
14
|
+
|
15
|
+
def ip
|
16
|
+
request.env['HTTP_X_FORWARDED_FOR'] || request.remote_ip
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_campus?(ip)
|
20
|
+
ip = remote_ip(ip)
|
21
|
+
ip_range_check(ip)
|
22
|
+
end
|
23
|
+
|
24
|
+
# To spoof ON and OFF campus for development
|
25
|
+
def remote_ip(ip)
|
26
|
+
if ip == '127.0.0.1'
|
27
|
+
'204.84.244.1' #On Campus
|
28
|
+
#'127.0.0.1' #Off Campus
|
29
|
+
else
|
30
|
+
ip
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def ip_range_check(ip)
|
35
|
+
QuickSearch::Engine::APP_CONFIG['on_campus'].each do |on_campus_ip_regex|
|
36
|
+
if on_campus_ip_regex === ip
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module QuickSearch::QueryFilter
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
include ActionView::Helpers::TextHelper
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def filter_query(query)
|
9
|
+
if query.match(/ -$/)
|
10
|
+
query = query.sub(/ -$/,"")
|
11
|
+
end
|
12
|
+
query.gsub!('*', ' ')
|
13
|
+
query.gsub!('!', ' ')
|
14
|
+
query.gsub!('-', ' ') # Solr returns an error if multiple dashes appear at start of query string
|
15
|
+
query.gsub!('\\', '')
|
16
|
+
# query.gsub!('"', '')
|
17
|
+
query.strip!
|
18
|
+
query.squish!
|
19
|
+
query.downcase! # FIXME: Do we really want to downcase everything?
|
20
|
+
query = truncate(query, length: 100, separator: ' ', omission: '', escape: false)
|
21
|
+
|
22
|
+
query
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module QuickSearch::QueryParser
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def extracted_query(unfiltered_query)
|
7
|
+
@unfiltered_query = unfiltered_query
|
8
|
+
if extracted_query_and_scope
|
9
|
+
query = extracted_query_and_scope[:query]
|
10
|
+
else
|
11
|
+
query = unfiltered_query
|
12
|
+
end
|
13
|
+
query
|
14
|
+
end
|
15
|
+
|
16
|
+
def extracted_scope(unfiltered_query)
|
17
|
+
@unfiltered_query = unfiltered_query
|
18
|
+
if extracted_query_and_scope
|
19
|
+
scope = extracted_query_and_scope[:value]
|
20
|
+
else
|
21
|
+
scope = ''
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def extracted_query_and_scope
|
26
|
+
if regex_matches = prefix_scope_multi_regex.match(@unfiltered_query)
|
27
|
+
regex_matches
|
28
|
+
elsif regex_matches = suffix_scope_multi_regex.match(@unfiltered_query)
|
29
|
+
regex_matches
|
30
|
+
elsif regex_matches = prefix_scope_regex.match(@unfiltered_query)
|
31
|
+
regex_matches
|
32
|
+
elsif regex_matches = suffix_scope_regex.match(@unfiltered_query)
|
33
|
+
regex_matches
|
34
|
+
end
|
35
|
+
regex_matches
|
36
|
+
end
|
37
|
+
|
38
|
+
def prefix_scope_regex
|
39
|
+
/^(?<option>scope):(?<value>\S+)\s?(?<query>.*)$/
|
40
|
+
end
|
41
|
+
|
42
|
+
def prefix_scope_multi_regex
|
43
|
+
/^(?<option>scope):\((?<value>.*?)\)\s?(?<query>.*)$/
|
44
|
+
end
|
45
|
+
|
46
|
+
def suffix_scope_regex
|
47
|
+
/(?<query>.*)\s(?<option>scope):(?<value>\S+)/
|
48
|
+
end
|
49
|
+
|
50
|
+
def suffix_scope_multi_regex
|
51
|
+
/^(?<query>.*)\s(?<option>scope):\((?<value>.*)\)$/
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module QuickSearch::SearcherConcern
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
include QuickSearch::OnCampus
|
5
|
+
include QuickSearch::QueryParser
|
6
|
+
include QuickSearch::EncodeUtf8
|
7
|
+
include QuickSearch::SearcherConfig
|
8
|
+
require 'benchmark_logger'
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def search_all_in_threads(primary_searcher = 'defaults')
|
13
|
+
benchmark "%s server ALL" % CGI.escape(query.to_str) do
|
14
|
+
search_threads = []
|
15
|
+
@found_types = [] # add the types that are found to a navigation bar
|
16
|
+
|
17
|
+
primary_searcher_config = ''
|
18
|
+
|
19
|
+
if primary_searcher == 'defaults'
|
20
|
+
searchers = QuickSearch::Engine::APP_CONFIG['searchers']
|
21
|
+
else
|
22
|
+
searcher_config = searcher_config(primary_searcher)
|
23
|
+
if searcher_config and searcher_config.has_key? 'with_paging'
|
24
|
+
searchers = searcher_config['with_paging']['searchers']
|
25
|
+
else
|
26
|
+
searchers = [primary_searcher]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
searchers.shuffle.each do |search_method|
|
31
|
+
search_threads << Thread.new(search_method) do |sm|
|
32
|
+
benchmark "%s server #{sm}" % CGI.escape(query.to_str) do
|
33
|
+
begin
|
34
|
+
klass = "QuickSearch::#{sm.camelize}Searcher".constantize
|
35
|
+
http_client = HTTPClient.new
|
36
|
+
update_searcher_timeout(http_client, search_method)
|
37
|
+
# FIXME: Probably want to set paging and offset somewhere else.
|
38
|
+
# searcher = klass.new(http_client, params_q_scrubbed, QuickSearch::Engine::APP_CONFIG['per_page'], 0, 1, on_campus?(request.remote_ip))
|
39
|
+
if sm == primary_searcher
|
40
|
+
if primary_searcher_config.has_key? 'with_paging'
|
41
|
+
per_page = primary_searcher_config['with_paging']['per_page']
|
42
|
+
else
|
43
|
+
per_page = 10
|
44
|
+
end
|
45
|
+
searcher = klass.new(http_client, query, per_page, offset(page, per_page), page, on_campus?(ip), scope)
|
46
|
+
else
|
47
|
+
searcher = klass.new(http_client, query, QuickSearch::Engine::APP_CONFIG['per_page'], 0, 1, on_campus?(ip), scope)
|
48
|
+
end
|
49
|
+
searcher.search
|
50
|
+
unless searcher.is_a? StandardError or searcher.results.blank?
|
51
|
+
@found_types.push(sm)
|
52
|
+
end
|
53
|
+
instance_variable_set "@#{sm}", searcher
|
54
|
+
rescue StandardError => e
|
55
|
+
# logger.info e
|
56
|
+
logger.info "FAILED SEARCH: #{sm} | #{params_q_scrubbed}"
|
57
|
+
instance_variable_set :"@#{sm.to_s}", e
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
search_threads.each {|t| t.join}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def page
|
68
|
+
if page_in_params?
|
69
|
+
page = params[:page].to_i
|
70
|
+
else
|
71
|
+
page = 1
|
72
|
+
end
|
73
|
+
page
|
74
|
+
end
|
75
|
+
|
76
|
+
def offset(page, per_page)
|
77
|
+
(page * per_page) - per_page
|
78
|
+
end
|
79
|
+
|
80
|
+
def query
|
81
|
+
extracted_query(params_q_scrubbed)
|
82
|
+
end
|
83
|
+
|
84
|
+
def scope
|
85
|
+
extracted_scope(params_q_scrubbed)
|
86
|
+
end
|
87
|
+
|
88
|
+
def update_searcher_timeout(client, search_method, xhr=false)
|
89
|
+
timeout_type = xhr ? 'xhr_http_timeout' : 'http_timeout'
|
90
|
+
timeout = QuickSearch::Engine::APP_CONFIG[timeout_type]
|
91
|
+
|
92
|
+
if QuickSearch::Engine::APP_CONFIG.has_key? search_method and QuickSearch::Engine::APP_CONFIG[search_method].has_key? timeout_type
|
93
|
+
timeout = QuickSearch::Engine::APP_CONFIG[search_method][timeout_type]
|
94
|
+
end
|
95
|
+
|
96
|
+
client.receive_timeout = timeout
|
97
|
+
client.send_timeout = timeout
|
98
|
+
client.connect_timeout = timeout
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module QuickSearch::SearcherConfig
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def searcher_config(searcher)
|
7
|
+
# Best Bets searcher is available in QuickSearch core, use app_config
|
8
|
+
if searcher == 'best_bets'
|
9
|
+
QuickSearch::Engine::APP_CONFIG['best_bets']
|
10
|
+
else
|
11
|
+
#TODO: test for the existence of this?
|
12
|
+
"QuickSearch::Engine::#{searcher.upcase}_CONFIG".constantize
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|