openstax_utilities 4.1.0 → 4.3.0
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.
- 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
|