openstax_utilities 4.1.0 → 4.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/app/routines/openstax/utilities/limit_and_paginate_relation.rb +85 -0
- data/app/routines/openstax/utilities/order_relation.rb +105 -0
- data/app/routines/openstax/utilities/search_and_organize_relation.rb +130 -0
- data/app/routines/openstax/utilities/search_relation.rb +94 -0
- data/lib/openstax/utilities/access_policy.rb +4 -3
- data/lib/openstax/utilities/assets.rb +29 -0
- data/lib/openstax/utilities/assets/manifest.rb +62 -0
- data/lib/openstax/utilities/version.rb +1 -1
- data/lib/openstax_utilities.rb +5 -5
- data/spec/cassettes/OpenStax_Utilities_Assets/loading_remote_manifest/uses_remote_json.yml +353 -0
- data/spec/dummy/app/access_policies/dummier_access_policy.rb +10 -0
- data/spec/dummy/app/assets/config/manifest.js +3 -0
- data/spec/dummy/config/application.rb +6 -11
- data/spec/dummy/config/environments/test.rb +1 -1
- data/spec/dummy/config/initializers/search_users.rb +26 -0
- data/spec/dummy/config/secrets.yml +2 -5
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/test.log +32144 -0
- data/spec/dummy/tmp/cache/C09/760/6da7b2a29da9cb0f80ef102c7effb91fab3374db +0 -0
- data/spec/factories/user.rb +1 -1
- data/spec/lib/openstax/utilities/access_policy_spec.rb +16 -15
- data/spec/lib/openstax/utilities/assets_spec.rb +40 -0
- data/spec/rails_helper.rb +1 -2
- data/spec/routines/openstax/utilities/limit_and_paginate_relation_spec.rb +72 -0
- data/spec/routines/openstax/utilities/order_relation_spec.rb +55 -0
- data/spec/routines/openstax/utilities/{abstract_keyword_search_routine_spec.rb → search_and_organize_relation_spec.rb} +54 -47
- data/spec/routines/openstax/utilities/search_relation_spec.rb +81 -0
- data/spec/vcr_helper.rb +18 -0
- metadata +123 -44
- data/app/handlers/openstax/utilities/keyword_search_handler.rb +0 -95
- data/app/routines/openstax/utilities/abstract_keyword_search_routine.rb +0 -158
- data/spec/dummy/app/routines/search_users.rb +0 -21
- data/spec/handlers/openstax/utilities/keyword_search_handler_spec.rb +0 -126
data/spec/vcr_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'vcr'
|
2
|
+
|
3
|
+
VCR.configure do |c|
|
4
|
+
c.cassette_library_dir = 'spec/cassettes'
|
5
|
+
c.hook_into :webmock
|
6
|
+
c.configure_rspec_metadata!
|
7
|
+
c.allow_http_connections_when_no_cassette = Rails.env.development?
|
8
|
+
c.ignore_localhost = true
|
9
|
+
c.ignore_request { |request| Addressable::URI.parse(request.uri).path == '/oauth/token' } \
|
10
|
+
if Rails.env.development?
|
11
|
+
c.preserve_exact_body_bytes { |http_message| !http_message.body.valid_encoding? }
|
12
|
+
end
|
13
|
+
|
14
|
+
VCR_OPTS = {
|
15
|
+
# This should default to :none
|
16
|
+
record: ENV.fetch('VCR_OPTS_RECORD', :none).to_sym,
|
17
|
+
allow_unused_http_interactions: Rails.env.development?
|
18
|
+
}
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openstax_utilities
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JP Slavinsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '5.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: lev
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +52,48 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: request_store
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: faraday
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: faraday-http-cache
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
55
97
|
- !ruby/object:Gem::Dependency
|
56
98
|
name: sqlite3
|
57
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,7 +123,7 @@ dependencies:
|
|
81
123
|
- !ruby/object:Gem::Version
|
82
124
|
version: '0'
|
83
125
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
126
|
+
name: factory_bot_rails
|
85
127
|
requirement: !ruby/object:Gem::Requirement
|
86
128
|
requirements:
|
87
129
|
- - ">="
|
@@ -109,7 +151,21 @@ dependencies:
|
|
109
151
|
- !ruby/object:Gem::Version
|
110
152
|
version: '0'
|
111
153
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
154
|
+
name: vcr
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: webmock
|
113
169
|
requirement: !ruby/object:Gem::Requirement
|
114
170
|
requirements:
|
115
171
|
- - ">="
|
@@ -132,14 +188,18 @@ files:
|
|
132
188
|
- MIT-LICENSE
|
133
189
|
- README.md
|
134
190
|
- Rakefile
|
135
|
-
- app/
|
136
|
-
- app/routines/openstax/utilities/
|
191
|
+
- app/routines/openstax/utilities/limit_and_paginate_relation.rb
|
192
|
+
- app/routines/openstax/utilities/order_relation.rb
|
193
|
+
- app/routines/openstax/utilities/search_and_organize_relation.rb
|
194
|
+
- app/routines/openstax/utilities/search_relation.rb
|
137
195
|
- app/views/osu/shared/_action_list.html.erb
|
138
196
|
- lib/openstax/utilities/access.rb
|
139
197
|
- lib/openstax/utilities/access_policy.rb
|
140
198
|
- lib/openstax/utilities/action_list.rb
|
141
199
|
- lib/openstax/utilities/active_record_extensions.rb
|
142
200
|
- lib/openstax/utilities/acts_as_numberable.rb
|
201
|
+
- lib/openstax/utilities/assets.rb
|
202
|
+
- lib/openstax/utilities/assets/manifest.rb
|
143
203
|
- lib/openstax/utilities/classy_helper.rb
|
144
204
|
- lib/openstax/utilities/delegate_access_control.rb
|
145
205
|
- lib/openstax/utilities/engine.rb
|
@@ -156,15 +216,17 @@ files:
|
|
156
216
|
- lib/openstax/utilities/text.rb
|
157
217
|
- lib/openstax/utilities/version.rb
|
158
218
|
- lib/openstax_utilities.rb
|
219
|
+
- spec/cassettes/OpenStax_Utilities_Assets/loading_remote_manifest/uses_remote_json.yml
|
159
220
|
- spec/dummy/README.md
|
160
221
|
- spec/dummy/Rakefile
|
222
|
+
- spec/dummy/app/access_policies/dummier_access_policy.rb
|
161
223
|
- spec/dummy/app/access_policies/dummy_access_policy.rb
|
224
|
+
- spec/dummy/app/assets/config/manifest.js
|
162
225
|
- spec/dummy/app/assets/javascripts/application.js
|
163
226
|
- spec/dummy/app/assets/stylesheets/application.css
|
164
227
|
- spec/dummy/app/controllers/application_controller.rb
|
165
228
|
- spec/dummy/app/helpers/application_helper.rb
|
166
229
|
- spec/dummy/app/models/user.rb
|
167
|
-
- spec/dummy/app/routines/search_users.rb
|
168
230
|
- spec/dummy/app/views/layouts/application.html.erb
|
169
231
|
- spec/dummy/bin/bundle
|
170
232
|
- spec/dummy/bin/rails
|
@@ -184,6 +246,7 @@ files:
|
|
184
246
|
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
185
247
|
- spec/dummy/config/initializers/inflections.rb
|
186
248
|
- spec/dummy/config/initializers/mime_types.rb
|
249
|
+
- spec/dummy/config/initializers/search_users.rb
|
187
250
|
- spec/dummy/config/initializers/session_store.rb
|
188
251
|
- spec/dummy/config/initializers/wrap_parameters.rb
|
189
252
|
- spec/dummy/config/locales/en.yml
|
@@ -191,16 +254,23 @@ files:
|
|
191
254
|
- spec/dummy/config/secrets.yml
|
192
255
|
- spec/dummy/db/migrate/0_create_users.rb
|
193
256
|
- spec/dummy/db/schema.rb
|
257
|
+
- spec/dummy/db/test.sqlite3
|
258
|
+
- spec/dummy/log/test.log
|
194
259
|
- spec/dummy/public/404.html
|
195
260
|
- spec/dummy/public/422.html
|
196
261
|
- spec/dummy/public/500.html
|
197
262
|
- spec/dummy/public/favicon.ico
|
263
|
+
- spec/dummy/tmp/cache/C09/760/6da7b2a29da9cb0f80ef102c7effb91fab3374db
|
198
264
|
- spec/factories/user.rb
|
199
|
-
- spec/handlers/openstax/utilities/keyword_search_handler_spec.rb
|
200
265
|
- spec/lib/openstax/utilities/access_policy_spec.rb
|
266
|
+
- spec/lib/openstax/utilities/assets_spec.rb
|
201
267
|
- spec/rails_helper.rb
|
202
|
-
- spec/routines/openstax/utilities/
|
268
|
+
- spec/routines/openstax/utilities/limit_and_paginate_relation_spec.rb
|
269
|
+
- spec/routines/openstax/utilities/order_relation_spec.rb
|
270
|
+
- spec/routines/openstax/utilities/search_and_organize_relation_spec.rb
|
271
|
+
- spec/routines/openstax/utilities/search_relation_spec.rb
|
203
272
|
- spec/spec_helper.rb
|
273
|
+
- spec/vcr_helper.rb
|
204
274
|
homepage: http://github.com/openstax/openstax_utilities
|
205
275
|
licenses:
|
206
276
|
- MIT
|
@@ -220,54 +290,63 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
220
290
|
- !ruby/object:Gem::Version
|
221
291
|
version: '0'
|
222
292
|
requirements: []
|
223
|
-
|
224
|
-
rubygems_version: 2.2.2
|
293
|
+
rubygems_version: 3.1.4
|
225
294
|
signing_key:
|
226
295
|
specification_version: 4
|
227
296
|
summary: Utilities for OpenStax web sites
|
228
297
|
test_files:
|
229
|
-
- spec/
|
298
|
+
- spec/rails_helper.rb
|
299
|
+
- spec/spec_helper.rb
|
300
|
+
- spec/vcr_helper.rb
|
301
|
+
- spec/factories/user.rb
|
302
|
+
- spec/dummy/app/models/user.rb
|
230
303
|
- spec/dummy/app/assets/javascripts/application.js
|
231
304
|
- spec/dummy/app/assets/stylesheets/application.css
|
305
|
+
- spec/dummy/app/assets/config/manifest.js
|
306
|
+
- spec/dummy/app/views/layouts/application.html.erb
|
307
|
+
- spec/dummy/app/access_policies/dummier_access_policy.rb
|
308
|
+
- spec/dummy/app/access_policies/dummy_access_policy.rb
|
232
309
|
- spec/dummy/app/controllers/application_controller.rb
|
233
310
|
- spec/dummy/app/helpers/application_helper.rb
|
234
|
-
- spec/dummy/
|
235
|
-
- spec/dummy/
|
236
|
-
- spec/dummy/
|
237
|
-
- spec/dummy/
|
311
|
+
- spec/dummy/tmp/cache/C09/760/6da7b2a29da9cb0f80ef102c7effb91fab3374db
|
312
|
+
- spec/dummy/db/migrate/0_create_users.rb
|
313
|
+
- spec/dummy/db/test.sqlite3
|
314
|
+
- spec/dummy/db/schema.rb
|
315
|
+
- spec/dummy/log/test.log
|
316
|
+
- spec/dummy/README.md
|
317
|
+
- spec/dummy/public/favicon.ico
|
318
|
+
- spec/dummy/public/422.html
|
319
|
+
- spec/dummy/public/404.html
|
320
|
+
- spec/dummy/public/500.html
|
321
|
+
- spec/dummy/config.ru
|
238
322
|
- spec/dummy/bin/rails
|
239
323
|
- spec/dummy/bin/rake
|
324
|
+
- spec/dummy/bin/bundle
|
240
325
|
- spec/dummy/config/application.rb
|
241
|
-
- spec/dummy/config/
|
242
|
-
- spec/dummy/config/
|
243
|
-
- spec/dummy/config/environment.rb
|
244
|
-
- spec/dummy/config/environments/development.rb
|
245
|
-
- spec/dummy/config/environments/production.rb
|
246
|
-
- spec/dummy/config/environments/test.rb
|
247
|
-
- spec/dummy/config/initializers/access_policies.rb
|
326
|
+
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
327
|
+
- spec/dummy/config/initializers/search_users.rb
|
248
328
|
- spec/dummy/config/initializers/assets.rb
|
249
|
-
- spec/dummy/config/initializers/backtrace_silencers.rb
|
250
329
|
- spec/dummy/config/initializers/cookies_serializer.rb
|
251
|
-
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
252
330
|
- spec/dummy/config/initializers/inflections.rb
|
253
|
-
- spec/dummy/config/initializers/
|
254
|
-
- spec/dummy/config/initializers/session_store.rb
|
331
|
+
- spec/dummy/config/initializers/backtrace_silencers.rb
|
255
332
|
- spec/dummy/config/initializers/wrap_parameters.rb
|
333
|
+
- spec/dummy/config/initializers/access_policies.rb
|
334
|
+
- spec/dummy/config/initializers/session_store.rb
|
335
|
+
- spec/dummy/config/initializers/mime_types.rb
|
256
336
|
- spec/dummy/config/locales/en.yml
|
257
337
|
- spec/dummy/config/routes.rb
|
338
|
+
- spec/dummy/config/database.yml
|
339
|
+
- spec/dummy/config/environment.rb
|
340
|
+
- spec/dummy/config/boot.rb
|
341
|
+
- spec/dummy/config/environments/production.rb
|
342
|
+
- spec/dummy/config/environments/test.rb
|
343
|
+
- spec/dummy/config/environments/development.rb
|
258
344
|
- spec/dummy/config/secrets.yml
|
259
|
-
- spec/dummy/config.ru
|
260
|
-
- spec/dummy/db/migrate/0_create_users.rb
|
261
|
-
- spec/dummy/db/schema.rb
|
262
|
-
- spec/dummy/public/404.html
|
263
|
-
- spec/dummy/public/422.html
|
264
|
-
- spec/dummy/public/500.html
|
265
|
-
- spec/dummy/public/favicon.ico
|
266
345
|
- spec/dummy/Rakefile
|
267
|
-
- spec/dummy/README.md
|
268
|
-
- spec/factories/user.rb
|
269
|
-
- spec/handlers/openstax/utilities/keyword_search_handler_spec.rb
|
270
346
|
- spec/lib/openstax/utilities/access_policy_spec.rb
|
271
|
-
- spec/
|
272
|
-
- spec/routines/openstax/utilities/
|
273
|
-
- spec/
|
347
|
+
- spec/lib/openstax/utilities/assets_spec.rb
|
348
|
+
- spec/routines/openstax/utilities/limit_and_paginate_relation_spec.rb
|
349
|
+
- spec/routines/openstax/utilities/search_relation_spec.rb
|
350
|
+
- spec/routines/openstax/utilities/order_relation_spec.rb
|
351
|
+
- spec/routines/openstax/utilities/search_and_organize_relation_spec.rb
|
352
|
+
- spec/cassettes/OpenStax_Utilities_Assets/loading_remote_manifest/uses_remote_json.yml
|
@@ -1,95 +0,0 @@
|
|
1
|
-
# Database-agnostic keyword searching handler
|
2
|
-
#
|
3
|
-
# Keywords have the format keyword:value
|
4
|
-
# Keywords can also be negated with -, as in -keyword:value
|
5
|
-
# Values are comma-separated, while keywords are space-separated
|
6
|
-
# See https://github.com/bruce/keyword_search for more information
|
7
|
-
#
|
8
|
-
# Callers must pass the search_routine and search_relation options:
|
9
|
-
#
|
10
|
-
# Required:
|
11
|
-
#
|
12
|
-
# search_routine - the Lev::Routine that will handle the search
|
13
|
-
# search_relation - the ActiveRecord::Relation that will be searched
|
14
|
-
#
|
15
|
-
# Optional (recommended to prevent scraping):
|
16
|
-
#
|
17
|
-
# min_characters - the minimum number of characters allowed in the query
|
18
|
-
# only an error will be returned if the query has less
|
19
|
-
# than the minimum number of characters allowed
|
20
|
-
# default: nil (disabled)
|
21
|
-
#
|
22
|
-
# max_items - the maximum number of matching items allowed to be returned
|
23
|
-
# no results will be returned if this number is exceeded,
|
24
|
-
# but the total result count will still be returned
|
25
|
-
# applies even if pagination is enabled
|
26
|
-
# default: nil (disabled)
|
27
|
-
#
|
28
|
-
# This handler also expects the following parameters from the user or the UI:
|
29
|
-
#
|
30
|
-
# Required:
|
31
|
-
#
|
32
|
-
# q - the query itself, a String that follows the keyword format above
|
33
|
-
#
|
34
|
-
# Optional:
|
35
|
-
#
|
36
|
-
# order_by - a String used to order the search results - default: 'created_at ASC'
|
37
|
-
# per_page - the number of results returned per page - default: nil (disabled)
|
38
|
-
# page - the current page number - default: 1
|
39
|
-
#
|
40
|
-
# This handler's output contains:
|
41
|
-
#
|
42
|
-
# outputs[:total_count] - the total number of items that matched the query
|
43
|
-
# set even when no results are returned due to
|
44
|
-
# a query that is too short or too generic
|
45
|
-
# outputs[:items] - the array of objects returned by the search routine
|
46
|
-
#
|
47
|
-
# See spec/dummy/app/handlers/users_search.rb for an example search handler
|
48
|
-
|
49
|
-
require 'lev'
|
50
|
-
|
51
|
-
module OpenStax
|
52
|
-
module Utilities
|
53
|
-
class KeywordSearchHandler
|
54
|
-
|
55
|
-
lev_handler
|
56
|
-
|
57
|
-
protected
|
58
|
-
|
59
|
-
def authorized?
|
60
|
-
routine = options[:search_routine]
|
61
|
-
relation = options[:search_relation]
|
62
|
-
raise ArgumentError if routine.nil? || relation.nil?
|
63
|
-
OSU::AccessPolicy.action_allowed?(:search, caller, relation.base_class)
|
64
|
-
end
|
65
|
-
|
66
|
-
def handle
|
67
|
-
query = params[:q]
|
68
|
-
fatal_error(code: :query_blank,
|
69
|
-
message: 'You must provide a query parameter (q or query).') if query.nil?
|
70
|
-
|
71
|
-
min_characters = options[:min_characters]
|
72
|
-
fatal_error(code: :query_too_short,
|
73
|
-
message: "The provided query is too short (minimum #{
|
74
|
-
min_characters} characters).") \
|
75
|
-
if !min_characters.nil? && query.length < min_characters
|
76
|
-
|
77
|
-
routine = options[:search_routine]
|
78
|
-
relation = options[:search_relation]
|
79
|
-
items = run(routine, relation, query, params).outputs[:items]
|
80
|
-
|
81
|
-
outputs[:total_count] = items.limit(nil).offset(nil).count
|
82
|
-
|
83
|
-
max_items = options[:max_items]
|
84
|
-
fatal_error(code: :too_many_items,
|
85
|
-
message: "The number of matches exceeded the allowed limit of #{
|
86
|
-
max_items} matches. Please refine your query and try again.") \
|
87
|
-
if !max_items.nil? && outputs[:total_count] > max_items
|
88
|
-
|
89
|
-
outputs[:items] = items.to_a
|
90
|
-
end
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
end
|
95
|
-
end
|
@@ -1,158 +0,0 @@
|
|
1
|
-
# Database-agnostic keyword searching routine
|
2
|
-
#
|
3
|
-
# Keywords have the format keyword:value
|
4
|
-
# Keywords can also be negated with -, as in -keyword:value
|
5
|
-
# Values are comma-separated, while keywords are space-separated
|
6
|
-
# See https://github.com/bruce/keyword_search for more information
|
7
|
-
#
|
8
|
-
# Subclasses must set the search_proc and sortable_fields class variables
|
9
|
-
#
|
10
|
-
# search_proc - a proc passed to keyword_search's `search` method
|
11
|
-
# it receives keyword_search's `with` object as argument
|
12
|
-
# this proc must define the `keyword` blocks for keyword_search
|
13
|
-
# the relation to be scoped is contained in the @items instance variable
|
14
|
-
# the `to_string_array` helper can help with
|
15
|
-
# parsing strings from the query
|
16
|
-
#
|
17
|
-
# sortable_fields_map - a Hash that maps the lowercase names of fields
|
18
|
-
# which can be used to sort the results to symbols
|
19
|
-
# for their respective database columns
|
20
|
-
# keys are lowercase strings that should be allowed
|
21
|
-
# in options[:order_by]
|
22
|
-
# values are the corresponding database column names
|
23
|
-
# that will be passed to the order() method
|
24
|
-
# columns from other tables can be specified either
|
25
|
-
# through Arel attributes (Class.arel_table[:column])
|
26
|
-
# or through literal strings
|
27
|
-
#
|
28
|
-
# Callers of subclass routines provide a relation argument,
|
29
|
-
# a query argument and an options hash
|
30
|
-
#
|
31
|
-
# Required arguments:
|
32
|
-
#
|
33
|
-
# relation - the initial relation to start searching on
|
34
|
-
# query - a string that follows the keyword format above
|
35
|
-
#
|
36
|
-
# Options hash:
|
37
|
-
#
|
38
|
-
# Ordering:
|
39
|
-
#
|
40
|
-
# :order_by - list of fields to sort by, with optional sort directions
|
41
|
-
# can be a String, Array of Strings or Array of Hashes
|
42
|
-
# default: {:created_at => :asc}
|
43
|
-
#
|
44
|
-
# Pagination:
|
45
|
-
#
|
46
|
-
# :per_page - the maximum number of results per page - default: nil (disabled)
|
47
|
-
# :page - the page to return - default: 1
|
48
|
-
#
|
49
|
-
# This routine's output contains:
|
50
|
-
#
|
51
|
-
# outputs[:items] - an ActiveRecord::Relation that matches the query terms and options
|
52
|
-
#
|
53
|
-
# You can use the following expression to obtain the
|
54
|
-
# total count of records that matched the query terms:
|
55
|
-
#
|
56
|
-
# outputs[:items].limit(nil).offset(nil).count
|
57
|
-
#
|
58
|
-
# See spec/dummy/app/routines/search_users.rb for an example search routine
|
59
|
-
|
60
|
-
require 'lev'
|
61
|
-
require 'keyword_search'
|
62
|
-
|
63
|
-
module OpenStax
|
64
|
-
module Utilities
|
65
|
-
class AbstractKeywordSearchRoutine
|
66
|
-
|
67
|
-
lev_routine transaction: :no_transaction
|
68
|
-
|
69
|
-
protected
|
70
|
-
|
71
|
-
class_attribute :search_proc, :sortable_fields_map
|
72
|
-
|
73
|
-
def exec(relation, query, options = {})
|
74
|
-
raise NotImplementedError if search_proc.nil? || sortable_fields_map.nil?
|
75
|
-
|
76
|
-
raise ArgumentError \
|
77
|
-
unless relation.is_a?(ActiveRecord::Relation) && query.is_a?(String)
|
78
|
-
|
79
|
-
@items = relation
|
80
|
-
|
81
|
-
# Scoping
|
82
|
-
|
83
|
-
::KeywordSearch.search(query) do |with|
|
84
|
-
instance_exec(with, &search_proc)
|
85
|
-
end
|
86
|
-
|
87
|
-
# Ordering
|
88
|
-
|
89
|
-
order_bys = sanitize_order_bys(options[:order_by])
|
90
|
-
@items = @items.order(order_bys)
|
91
|
-
|
92
|
-
# Pagination
|
93
|
-
|
94
|
-
per_page = Integer(options[:per_page]) rescue nil
|
95
|
-
unless per_page.nil?
|
96
|
-
page = Integer(options[:page]) rescue 1
|
97
|
-
@items = @items.limit(per_page).offset(per_page*(page-1))
|
98
|
-
end
|
99
|
-
|
100
|
-
outputs[:items] = @items
|
101
|
-
end
|
102
|
-
|
103
|
-
def sanitize_order_by(field, dir = nil)
|
104
|
-
sanitized_field = sortable_fields_map[field.to_s.downcase] || :created_at
|
105
|
-
sanitized_dir = dir.to_s.downcase == 'desc' ? :desc : :asc
|
106
|
-
case sanitized_field
|
107
|
-
when Symbol
|
108
|
-
{sanitized_field => sanitized_dir}
|
109
|
-
when Arel::Attributes::Attribute
|
110
|
-
sanitized_field.send sanitized_dir
|
111
|
-
else
|
112
|
-
"#{sanitized_field.to_s} #{sanitized_dir.to_s.upcase}"
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def sanitize_order_bys(order_bys)
|
117
|
-
case order_bys
|
118
|
-
when Array
|
119
|
-
order_bys.collect do |ob|
|
120
|
-
case ob
|
121
|
-
when Hash
|
122
|
-
sanitize_order_by(ob.keys.first, ob.values.first)
|
123
|
-
when Array
|
124
|
-
sanitize_order_by(ob.first, ob.second)
|
125
|
-
else
|
126
|
-
sanitize_order_by(ob)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
when Hash
|
130
|
-
order_bys.collect { |k, v| sanitize_order_by(k, v) }
|
131
|
-
else
|
132
|
-
order_bys.to_s.split(',').collect do |ob|
|
133
|
-
fd = ob.split(' ')
|
134
|
-
sanitize_order_by(fd.first, fd.second)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
# Parses a keyword string into an array of strings
|
140
|
-
# User-supplied wildcards are removed and strings are split on commas
|
141
|
-
# Then wildcards are appended or prepended if the append_wildcard or
|
142
|
-
# prepend_wildcard options are specified
|
143
|
-
def to_string_array(str, options = {})
|
144
|
-
sa = case str
|
145
|
-
when Array
|
146
|
-
str.collect{|name| name.gsub('%', '').split(',')}.flatten
|
147
|
-
else
|
148
|
-
str.to_s.gsub('%', '').split(',')
|
149
|
-
end
|
150
|
-
sa = sa.collect{|str| "#{str}%"} if options[:append_wildcard]
|
151
|
-
sa = sa.collect{|str| "%#{str}"} if options[:prepend_wildcard]
|
152
|
-
sa
|
153
|
-
end
|
154
|
-
|
155
|
-
end
|
156
|
-
|
157
|
-
end
|
158
|
-
end
|