quick_search-core 0.0.1.test

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.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +168 -0
  4. data/Rakefile +6 -0
  5. data/app/assets/images/quick_search/askus.gif +0 -0
  6. data/app/assets/images/quick_search/favicon.ico +0 -0
  7. data/app/assets/images/quick_search/greybox.png +0 -0
  8. data/app/assets/images/quick_search/homescreen-icon-64x64.png +0 -0
  9. data/app/assets/images/quick_search/ncsu-library-logo-white.png +0 -0
  10. data/app/assets/javascripts/quick_search/appstats.js +8 -0
  11. data/app/assets/javascripts/quick_search/event_tracking.js.erb +257 -0
  12. data/app/assets/javascripts/quick_search/google_analytics.js.erb +8 -0
  13. data/app/assets/javascripts/quick_search/opensearch.js +2 -0
  14. data/app/assets/javascripts/quick_search/pages.js.coffee +3 -0
  15. data/app/assets/javascripts/quick_search/quicksearch.js +33 -0
  16. data/app/assets/javascripts/quick_search/realtime.js.erb +12 -0
  17. data/app/assets/javascripts/quick_search/search.js +3 -0
  18. data/app/assets/javascripts/quick_search/xhr_search.js +82 -0
  19. data/app/assets/javascripts/quick_search.js.erb +20 -0
  20. data/app/assets/stylesheets/foundation_and_overrides.scss +1327 -0
  21. data/app/assets/stylesheets/quick_search/appstats.css.scss +7 -0
  22. data/app/assets/stylesheets/quick_search/opensearch.css.scss +3 -0
  23. data/app/assets/stylesheets/quick_search/pages.css.scss +3 -0
  24. data/app/assets/stylesheets/quick_search/quick_search.css.scss +248 -0
  25. data/app/assets/stylesheets/quick_search/search.css.scss +3 -0
  26. data/app/assets/stylesheets/quick_search.css.scss.erb +7 -0
  27. data/app/controllers/concerns/quick_search/auth.rb +22 -0
  28. data/app/controllers/concerns/quick_search/doi_trap.rb +43 -0
  29. data/app/controllers/concerns/quick_search/encode_utf8.rb +12 -0
  30. data/app/controllers/concerns/quick_search/on_campus.rb +43 -0
  31. data/app/controllers/concerns/quick_search/query_filter.rb +25 -0
  32. data/app/controllers/concerns/quick_search/query_parser.rb +54 -0
  33. data/app/controllers/concerns/quick_search/searcher_concern.rb +101 -0
  34. data/app/controllers/concerns/quick_search/searcher_config.rb +16 -0
  35. data/app/controllers/quick_search/application_controller.rb +7 -0
  36. data/app/controllers/quick_search/appstats_controller.rb +210 -0
  37. data/app/controllers/quick_search/opensearch_controller.rb +9 -0
  38. data/app/controllers/quick_search/pages_controller.rb +18 -0
  39. data/app/controllers/quick_search/search_controller.rb +250 -0
  40. data/app/helpers/quick_search/application_helper.rb +68 -0
  41. data/app/helpers/quick_search/appstats_helper.rb +2 -0
  42. data/app/helpers/quick_search/opensearch_helper.rb +2 -0
  43. data/app/helpers/quick_search/pages_helper.rb +2 -0
  44. data/app/helpers/quick_search/search_helper.rb +2 -0
  45. data/app/models/event.rb +2 -0
  46. data/app/models/search.rb +11 -0
  47. data/app/searchers/quick_search/best_bets_searcher.rb +102 -0
  48. data/app/searchers/quick_search/searcher.rb +43 -0
  49. data/app/views/layouts/quick_search/_best_bets.html.erb +18 -0
  50. data/app/views/layouts/quick_search/_common_searches.html.erb +15 -0
  51. data/app/views/layouts/quick_search/_found_types.html.erb +13 -0
  52. data/app/views/layouts/quick_search/_google_analytics.html.erb +24 -0
  53. data/app/views/layouts/quick_search/_more_options.html.erb +10 -0
  54. data/app/views/layouts/quick_search/_page_title.html.erb +8 -0
  55. data/app/views/layouts/quick_search/_related_topics.html.erb +8 -0
  56. data/app/views/layouts/quick_search/_search_form.html.erb +19 -0
  57. data/app/views/layouts/quick_search/_spelling_suggestion.html.erb +13 -0
  58. data/app/views/layouts/quick_search/_topic_snippet.html.erb +5 -0
  59. data/app/views/layouts/quick_search/application.html.erb +40 -0
  60. data/app/views/quick_search/appstats/_click_count_table.html.erb +23 -0
  61. data/app/views/quick_search/appstats/_datatables.html.erb +12 -0
  62. data/app/views/quick_search/appstats/_date_range.html.erb +15 -0
  63. data/app/views/quick_search/appstats/_menu.html.erb +16 -0
  64. data/app/views/quick_search/appstats/_top_spot_report_table.html.erb +33 -0
  65. data/app/views/quick_search/appstats/clicks_overview.html.erb +20 -0
  66. data/app/views/quick_search/appstats/index.html.erb +31 -0
  67. data/app/views/quick_search/appstats/module_click_detail.html.erb +32 -0
  68. data/app/views/quick_search/appstats/realtime.html.erb +15 -0
  69. data/app/views/quick_search/appstats/top_searches.html.erb +38 -0
  70. data/app/views/quick_search/appstats/top_spot.html.erb +14 -0
  71. data/app/views/quick_search/appstats/top_spot_detail.html.erb +35 -0
  72. data/app/views/quick_search/kaminari/_first_page.html.erb +12 -0
  73. data/app/views/quick_search/kaminari/_gap.html.erb +11 -0
  74. data/app/views/quick_search/kaminari/_last_page.html.erb +12 -0
  75. data/app/views/quick_search/kaminari/_next_page.html.erb +12 -0
  76. data/app/views/quick_search/kaminari/_page.html.erb +13 -0
  77. data/app/views/quick_search/kaminari/_paginator.html.erb +25 -0
  78. data/app/views/quick_search/kaminari/_prev_page.html.erb +11 -0
  79. data/app/views/quick_search/opensearch/opensearch.xml.builder +11 -0
  80. data/app/views/quick_search/pages/about.html.erb +9 -0
  81. data/app/views/quick_search/pages/home.html.erb +6 -0
  82. data/app/views/quick_search/pages/realtime.html.erb +15 -0
  83. data/app/views/quick_search/search/_citation.html.erb +18 -0
  84. data/app/views/quick_search/search/_module.html.erb +37 -0
  85. data/app/views/quick_search/search/_module_with_paging.html.erb +14 -0
  86. data/app/views/quick_search/search/_no_results.html.erb +11 -0
  87. data/app/views/quick_search/search/_result.html.erb +17 -0
  88. data/app/views/quick_search/search/_result_details.html.erb +45 -0
  89. data/app/views/quick_search/search/_result_no_thumbnail.html.erb +3 -0
  90. data/app/views/quick_search/search/_result_title.html.erb +4 -0
  91. data/app/views/quick_search/search/_result_with_thumbnail.html.erb +21 -0
  92. data/app/views/quick_search/search/_search_error.html.erb +9 -0
  93. data/app/views/quick_search/search/_see_all.html.erb +11 -0
  94. data/app/views/quick_search/search/_xhr_response.html.erb +15 -0
  95. data/app/views/quick_search/search/_xhr_response.json.erb +14 -0
  96. data/app/views/quick_search/search/_xhr_response_with_paging.html.erb +1 -0
  97. data/app/views/quick_search/search/index.html.erb +100 -0
  98. data/config/application.rb +25 -0
  99. data/config/best_bets.yml +86 -0
  100. data/config/boot.rb +4 -0
  101. data/config/database.yml.example +31 -0
  102. data/config/locales/en.yml +30 -0
  103. data/config/quicksearch_config.yml.example +69 -0
  104. data/config/routes.rb +81 -0
  105. data/db/migrate/20140130202859_create_events.rb +11 -0
  106. data/db/migrate/20140130202944_create_searches.rb +9 -0
  107. data/db/migrate/20140225145441_add_page_to_searches.rb +5 -0
  108. data/db/schema.rb +31 -0
  109. data/db/seeds.rb +7 -0
  110. data/lib/benchmark_logger.rb +2 -0
  111. data/lib/capistrano/tasks/access_check.cap +10 -0
  112. data/lib/generators/quick_search/install_generator.rb +49 -0
  113. data/lib/generators/quick_search/templates/kaminari.rb +5 -0
  114. data/lib/generators/quick_search/templates/post_install.txt +8 -0
  115. data/lib/generators/quick_search/templates/quick_search_config.yml +58 -0
  116. data/lib/quick_search/engine.rb +16 -0
  117. data/lib/quick_search/version.rb +3 -0
  118. data/lib/quick_search.rb +12 -0
  119. data/lib/tasks/best_bets.rake +29 -0
  120. data/test/controllers/appstats_controller_test.rb +7 -0
  121. data/test/controllers/concerns/doi_trap_test.rb +19 -0
  122. data/test/controllers/concerns/on_campus_test.rb +19 -0
  123. data/test/controllers/concerns/query_parser_test.rb +47 -0
  124. data/test/controllers/opensearch_controller_test.rb +13 -0
  125. data/test/controllers/pages_controller_test.rb +7 -0
  126. data/test/controllers/search_controller_test.rb +15 -0
  127. data/test/fixtures/events.yml +11 -0
  128. data/test/fixtures/searches.yml +7 -0
  129. data/test/helpers/appstats_helper_test.rb +4 -0
  130. data/test/helpers/opensearch_helper_test.rb +4 -0
  131. data/test/helpers/pages_helper_test.rb +4 -0
  132. data/test/helpers/search_helper_test.rb +4 -0
  133. data/test/integration/catalog_search_test.rb +8 -0
  134. data/test/integration/google_analytics_test.rb +23 -0
  135. data/test/integration/landing_page_test.rb +8 -0
  136. data/test/integration/searching_test.rb +40 -0
  137. data/test/integration/smart_subjects_test.rb +8 -0
  138. data/test/integration/website_search_test.rb +8 -0
  139. data/test/models/event_test.rb +7 -0
  140. data/test/models/search_test.rb +7 -0
  141. data/test/searcher/best_bets_test.rb +35 -0
  142. data/test/searcher/catalog_test.rb +35 -0
  143. data/test/searcher/ematrix_database_test.rb +27 -0
  144. data/test/searcher/ematrix_journal_test.rb +27 -0
  145. data/test/searcher/faq_test.rb +27 -0
  146. data/test/searcher/smart_subjects_test.rb +27 -0
  147. data/test/searcher/summon_test.rb +13 -0
  148. data/test/searcher/website_test.rb +34 -0
  149. data/test/support/vcr_test.rb +40 -0
  150. data/test/test_helper.rb +42 -0
  151. metadata +366 -0
@@ -0,0 +1,7 @@
1
+ // Place all the styles related to the Appstats controller here.
2
+ // They will automatically be included in application.css.
3
+ // You can use Sass (SCSS) here: http://sass-lang.com/
4
+
5
+ #appstats-date-filter {
6
+ display: none;
7
+ }
@@ -0,0 +1,3 @@
1
+ // Place all the styles related to the opensearch controller here.
2
+ // They will automatically be included in application.css.
3
+ // You can use Sass (SCSS) here: http://sass-lang.com/
@@ -0,0 +1,3 @@
1
+ // Place all the styles related to the pages controller here.
2
+ // They will automatically be included in application.css.
3
+ // You can use Sass (SCSS) here: http://sass-lang.com/
@@ -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,3 @@
1
+ // Place all the styles related to the search controller here.
2
+ // They will automatically be included in application.css.
3
+ // You can use Sass (SCSS) here: http://sass-lang.com/
@@ -0,0 +1,7 @@
1
+ @import "<%= QuickSearch::Engine::APP_CONFIG['theme'] %>";
2
+ @import "quick_search/quick_search";
3
+ @import "quick_search/pages";
4
+ @import "quick_search/search";
5
+ @import "quick_search/appstats";
6
+ // @import "typeahead";
7
+ //
@@ -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,12 @@
1
+ module QuickSearch::EncodeUtf8
2
+ extend ActiveSupport::Concern
3
+
4
+ private
5
+
6
+ def params_q_scrubbed
7
+ unless params[:q].nil?
8
+ params[:q].scrub
9
+ end
10
+ end
11
+
12
+ 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
@@ -0,0 +1,7 @@
1
+ module QuickSearch
2
+ class ApplicationController < ::ApplicationController
3
+ # Prevent CSRF attacks by raising an exception.
4
+ # For APIs, you may want to use :null_session instead.
5
+ protect_from_forgery with: :exception
6
+ end
7
+ end