berkeley_library-alma 0.0.1

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 (46) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/build.yml +18 -0
  3. data/.gitignore +388 -0
  4. data/.idea/.gitignore +8 -0
  5. data/.idea/alma.iml +55 -0
  6. data/.idea/codeStyles/codeStyleConfig.xml +5 -0
  7. data/.idea/inspectionProfiles/Project_Default.xml +26 -0
  8. data/.idea/misc.xml +4 -0
  9. data/.idea/modules.xml +8 -0
  10. data/.idea/vcs.xml +6 -0
  11. data/.rubocop.yml +334 -0
  12. data/.ruby-version +1 -0
  13. data/.simplecov +8 -0
  14. data/.yardopts +2 -0
  15. data/CHANGES.md +3 -0
  16. data/Dockerfile +54 -0
  17. data/Gemfile +3 -0
  18. data/Jenkinsfile +18 -0
  19. data/LICENSE.md +21 -0
  20. data/README.md +210 -0
  21. data/Rakefile +20 -0
  22. data/berkeley_library-alma.gemspec +42 -0
  23. data/bin/alma-mms-lookup +64 -0
  24. data/docker-compose.yml +15 -0
  25. data/lib/berkeley_library/alma/bib_number.rb +90 -0
  26. data/lib/berkeley_library/alma/config.rb +178 -0
  27. data/lib/berkeley_library/alma/constants.rb +16 -0
  28. data/lib/berkeley_library/alma/mms_id.rb +100 -0
  29. data/lib/berkeley_library/alma/module_info.rb +14 -0
  30. data/lib/berkeley_library/alma/record_id.rb +113 -0
  31. data/lib/berkeley_library/alma.rb +1 -0
  32. data/rakelib/bundle.rake +8 -0
  33. data/rakelib/coverage.rake +11 -0
  34. data/rakelib/gem.rake +54 -0
  35. data/rakelib/rubocop.rake +18 -0
  36. data/rakelib/spec.rake +2 -0
  37. data/spec/.rubocop.yml +37 -0
  38. data/spec/data/991054360089706532-sru.xml +186 -0
  39. data/spec/data/b11082434-sru.xml +165 -0
  40. data/spec/data/bibs_with_check_digits.txt +151 -0
  41. data/spec/lib/berkeley_library/alma/bib_number_spec.rb +95 -0
  42. data/spec/lib/berkeley_library/alma/config_spec.rb +94 -0
  43. data/spec/lib/berkeley_library/alma/mms_id_spec.rb +111 -0
  44. data/spec/lib/berkeley_library/alma/record_id_spec.rb +41 -0
  45. data/spec/spec_helper.rb +56 -0
  46. metadata +325 -0
data/.rubocop.yml ADDED
@@ -0,0 +1,334 @@
1
+ inherit_mode:
2
+ merge:
3
+ - Exclude
4
+ - Include
5
+
6
+ # Allow one line around block body (Layout/EmptyLines will still disallow two or more)
7
+ Layout/EmptyLinesAroundBlockBody:
8
+ Enabled: false
9
+
10
+ # Allow one line around class body (Layout/EmptyLines will still disallow two or more)
11
+ Layout/EmptyLinesAroundClassBody:
12
+ Enabled: false
13
+
14
+ # Allow one line around module body (Layout/EmptyLines will still disallow two or more)
15
+ Layout/EmptyLinesAroundModuleBody:
16
+ Enabled: false
17
+
18
+ # Reasonable line-length check; it's too easy for the cure to be worse than the disease
19
+ Layout/LineLength:
20
+ Max: 150
21
+
22
+ # Make indents consistent regardless of the lengths of variables and method names and whatnot
23
+ Layout/MultilineMethodCallIndentation:
24
+ EnforcedStyle: indented
25
+
26
+ # Produces monsters
27
+ Layout/MultilineOperationIndentation:
28
+ Enabled: false
29
+
30
+ # We meant to do that
31
+ Naming/MemoizedInstanceVariableName:
32
+ Enabled: False
33
+
34
+ # It works in context, trust us
35
+ Naming/MethodParameterName:
36
+ Enabled: False
37
+
38
+ # Confusing and weird
39
+ Naming/VariableNumber:
40
+ Enabled: False
41
+
42
+ # Do what's readable in the context you're in
43
+ Style/AccessModifierDeclarations:
44
+ Enabled: false
45
+
46
+ # 👎 to cultural imperialism
47
+ Style/AsciiComments:
48
+ Enabled: false
49
+
50
+ # Seriously?
51
+ Style/CommentedKeyword:
52
+ Enabled: False
53
+
54
+ # Disable problematic module documentation check (see https://github.com/bbatsov/rubocop/issues/947)
55
+ Style/Documentation:
56
+ Enabled: false
57
+
58
+ # Adding more line noise to format strings will not improve them
59
+ Style/FormatStringToken:
60
+ Enabled: false
61
+
62
+ # Putting '# frozen_string_literal: true' everywhere does not make the world a better place
63
+ Style/FrozenStringLiteralComment:
64
+ Enabled: false
65
+
66
+ # Requiring the lambda() method just makes wordy calls wordier
67
+ Style/Lambda:
68
+ EnforcedStyle: literal
69
+
70
+ # `foo.positive?` is cute, but it's not actually more readable than `foo > 0`
71
+ Style/NumericPredicate:
72
+ Enabled: false
73
+
74
+ # Unclear why it's a good idea to give parameters semantically meaningless names
75
+ Style/SingleLineBlockParams:
76
+ Enabled: false
77
+
78
+ # The semantics of `foo&.bar` are a lot less interchangeable with `foo && foo.bar` than RuboCop thinks
79
+ Style/SafeNavigation:
80
+ Enabled: false
81
+
82
+ # Short arrays are often more readable as plain arrays
83
+ Style/WordArray:
84
+ MinSize: 3
85
+
86
+ ############################################################
87
+ # Added in RuboCop 0.80
88
+
89
+ Style/HashEachMethods:
90
+ Enabled: true
91
+
92
+ Style/HashTransformKeys:
93
+ Enabled: true
94
+
95
+ Style/HashTransformValues:
96
+ Enabled: true
97
+
98
+ ############################################################
99
+ # Added in RuboCop 0.81
100
+
101
+ Lint/StructNewOverride:
102
+ Enabled: true
103
+
104
+ Lint/RaiseException:
105
+ Enabled: true
106
+
107
+ ############################################################
108
+ # Added in RuboCop 0.82
109
+
110
+ Layout/SpaceAroundMethodCallOperator:
111
+ Enabled: true
112
+
113
+ Style/ExponentialNotation:
114
+ Enabled: false
115
+
116
+ ############################################################
117
+ # Added in RuboCop 0.83
118
+
119
+ Layout/EmptyLinesAroundAttributeAccessor:
120
+ Enabled: true
121
+
122
+ Style/SlicingWithRange:
123
+ Enabled: true
124
+
125
+ ############################################################
126
+ # Added in RuboCop 0.84
127
+
128
+ Lint/DeprecatedOpenSSLConstant:
129
+ Enabled: true
130
+
131
+ ############################################################
132
+ # Added in RuboCop 0.85
133
+
134
+ Lint/MixedRegexpCaptureTypes:
135
+ Enabled: true
136
+
137
+ Style/RedundantRegexpEscape:
138
+ Enabled: true
139
+
140
+ Style/RedundantRegexpCharacterClass:
141
+ Enabled: true
142
+
143
+ ############################################################
144
+ # Added in Rubocop 0.86
145
+
146
+ Style/RedundantFetchBlock:
147
+ Enabled: true
148
+
149
+ ############################################################
150
+ # Added in Rubocop 0.87
151
+
152
+ # Sometimes we separate things for a reason
153
+ Style/AccessorGrouping:
154
+ Enabled: false
155
+
156
+ Style/BisectedAttrAccessor:
157
+ Enabled: true
158
+
159
+ Style/RedundantAssignment:
160
+ Enabled: true
161
+
162
+ ############################################################
163
+ # Added in Rubocop 0.88
164
+
165
+ Lint/DuplicateElsifCondition:
166
+ Enabled: true
167
+
168
+ Style/ArrayCoercion:
169
+ Enabled: true
170
+
171
+ Style/CaseLikeIf:
172
+ Enabled: true
173
+
174
+ Style/HashAsLastArrayItem:
175
+ Enabled: true
176
+
177
+ Style/HashLikeCase:
178
+ Enabled: true
179
+
180
+ Style/RedundantFileExtensionInRequire:
181
+ Enabled: true
182
+
183
+ ############################################################
184
+ # Added in Rubocop 0.89
185
+
186
+ Lint/BinaryOperatorWithIdenticalOperands:
187
+ Enabled: true
188
+
189
+ Lint/DuplicateRescueException:
190
+ Enabled: true
191
+
192
+ Lint/EmptyConditionalBody:
193
+ Enabled: true
194
+
195
+ Lint/FloatComparison:
196
+ Enabled: true
197
+
198
+ Lint/MissingSuper:
199
+ Enabled: true
200
+
201
+ Lint/OutOfRangeRegexpRef:
202
+ Enabled: true
203
+
204
+ Lint/SelfAssignment:
205
+ Enabled: true
206
+
207
+ Lint/TopLevelReturnWithArgument:
208
+ Enabled: true
209
+
210
+ Lint/UnreachableLoop:
211
+ Enabled: true
212
+
213
+ Style/ExplicitBlockArgument:
214
+ Enabled: true
215
+
216
+ Style/GlobalStdStream:
217
+ Enabled: true
218
+
219
+ Style/OptionalBooleanParameter:
220
+ Enabled: true
221
+
222
+ Style/SingleArgumentDig:
223
+ Enabled: true
224
+
225
+ Style/SoleNestedConditional:
226
+ Enabled: true
227
+
228
+ Style/StringConcatenation:
229
+ Enabled: true
230
+
231
+ ############################################################
232
+ # Added in Rubocop 0.90
233
+
234
+ Lint/DuplicateRequire:
235
+ Enabled: true
236
+
237
+ Lint/EmptyFile:
238
+ Enabled: true
239
+
240
+ Lint/TrailingCommaInAttributeDeclaration:
241
+ Enabled: true
242
+
243
+ Lint/UselessMethodDefinition:
244
+ Enabled: true
245
+
246
+ Style/CombinableLoops:
247
+ Enabled: true
248
+
249
+ Style/KeywordParametersOrder:
250
+ Enabled: true
251
+
252
+ Style/RedundantSelfAssignment:
253
+ Enabled: true
254
+
255
+ ############################################################
256
+ # Added in Rubocop 0.91
257
+
258
+ Layout/BeginEndAlignment:
259
+ Enabled: true
260
+
261
+ Lint/ConstantDefinitionInBlock:
262
+ Enabled: true
263
+
264
+ Lint/IdentityComparison:
265
+ Enabled: true
266
+
267
+ Lint/UselessTimes:
268
+ Enabled: true
269
+
270
+ ############################################################
271
+ # Added in Rubocop 1.1–1.9
272
+
273
+ Layout/SpaceBeforeBrackets: # (new in 1.7)
274
+ Enabled: true
275
+ Lint/AmbiguousAssignment: # (new in 1.7)
276
+ Enabled: true
277
+ Lint/DeprecatedConstants: # (new in 1.8)
278
+ Enabled: true
279
+ Lint/DuplicateBranch: # (new in 1.3)
280
+ Enabled: true
281
+ Lint/DuplicateRegexpCharacterClassElement: # (new in 1.1)
282
+ Enabled: true
283
+ Lint/EmptyBlock: # (new in 1.1)
284
+ Enabled: true
285
+ Lint/EmptyClass: # (new in 1.3)
286
+ Enabled: true
287
+ Lint/LambdaWithoutLiteralBlock: # (new in 1.8)
288
+ Enabled: true
289
+ Lint/NoReturnInBeginEndBlocks: # (new in 1.2)
290
+ Enabled: true
291
+ Lint/NumberedParameterAssignment: # (new in 1.9)
292
+ Enabled: true
293
+ Lint/OrAssignmentToConstant: # (new in 1.9)
294
+ Enabled: true
295
+ Lint/RedundantDirGlobSort: # (new in 1.8)
296
+ Enabled: true
297
+ Lint/SymbolConversion: # (new in 1.9)
298
+ Enabled: true
299
+ Lint/ToEnumArguments: # (new in 1.1)
300
+ Enabled: true
301
+ Lint/TripleQuotes: # (new in 1.9)
302
+ Enabled: true
303
+ Lint/UnexpectedBlockArity: # (new in 1.5)
304
+ Enabled: true
305
+ Lint/UnmodifiedReduceAccumulator: # (new in 1.1)
306
+ Enabled: true
307
+ Style/ArgumentsForwarding: # (new in 1.1)
308
+ Enabled: true
309
+ Style/CollectionCompact: # (new in 1.2)
310
+ Enabled: true
311
+ Style/DocumentDynamicEvalDefinition: # (new in 1.1)
312
+ Enabled: true
313
+ Style/EndlessMethod: # (new in 1.8)
314
+ Enabled: true
315
+ Style/HashExcept: # (new in 1.7)
316
+ Enabled: true
317
+ Style/IfWithBooleanLiteralBranches: # (new in 1.9)
318
+ Enabled: true
319
+ Style/NegatedIfElseCondition: # (new in 1.2)
320
+ Enabled: true
321
+ Style/NilLambda: # (new in 1.3)
322
+ Enabled: true
323
+ Style/RedundantArgument: # (new in 1.4)
324
+ Enabled: true
325
+ Style/SwapValues: # (new in 1.1)
326
+ Enabled: true
327
+
328
+ ############################################################
329
+ # Added in RuboCop 1.10
330
+
331
+ Gemspec/DateAssignment: # (new in 1.10)
332
+ Enabled: true
333
+ Style/HashConversion: # (new in 1.10)
334
+ Enabled: true
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.7.5
data/.simplecov ADDED
@@ -0,0 +1,8 @@
1
+ require 'simplecov-rcov'
2
+
3
+ SimpleCov.start 'rails' do
4
+ add_filter 'module_info.rb'
5
+ coverage_dir 'artifacts'
6
+ formatter SimpleCov::Formatter::RcovFormatter
7
+ minimum_coverage 100
8
+ end
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ -m markdown
2
+ -o ./artifacts/doc
data/CHANGES.md ADDED
@@ -0,0 +1,3 @@
1
+ # 0.0.1 (25 January 2022)
2
+
3
+ - initial public release
data/Dockerfile ADDED
@@ -0,0 +1,54 @@
1
+ # =============================================================================
2
+ # Target: base
3
+
4
+ FROM ruby:3.0.2-alpine AS base
5
+
6
+ RUN apk --no-cache --update upgrade && \
7
+ apk --no-cache add \
8
+ bash \
9
+ ca-certificates \
10
+ git \
11
+ libc6-compat \
12
+ openssl \
13
+ tzdata \
14
+ xz-libs \
15
+ && rm -rf /var/cache/apk/*
16
+
17
+ WORKDIR /opt/app
18
+
19
+ # =============================================================================
20
+ # Target: development
21
+ #
22
+
23
+ FROM base AS development
24
+
25
+ # Install system packages needed to build gems with C extensions.
26
+ RUN apk --update --no-cache add \
27
+ build-base \
28
+ coreutils \
29
+ git \
30
+ && rm -rf /var/cache/apk/*
31
+
32
+ # Copy codebase to WORKDIR. Unlike application projects, for a gem project
33
+ # we need to do this before running `bundle install`, in order for the gem
34
+ # we're building to be able to "install" itself.
35
+ COPY . .
36
+
37
+ # Install gems.
38
+ RUN bundle install --path=/usr/local/bundle
39
+
40
+ # =============================================================================
41
+ # Target: production
42
+
43
+ FROM base AS production
44
+
45
+ # Copy the built codebase from the dev stage
46
+ COPY --from=development /opt/app /opt/app
47
+ COPY --from=development /usr/local/bundle /usr/local/bundle
48
+
49
+ # Sanity-check that everything was installed correctly and still runs in the
50
+ # slimmed-down production image.
51
+ RUN bundle config set deployment 'true'
52
+ RUN bundle install --local --path=/usr/local/bundle
53
+
54
+ CMD ['bundle', 'exec', 'rake']
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Jenkinsfile ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env groovy
2
+
3
+ dockerComposePipeline(
4
+ commands: [
5
+ 'bundle exec rake coverage',
6
+ 'bundle exec rake rubocop',
7
+ 'bundle exec rake bundle:audit',
8
+ 'bundle exec rake gem'
9
+ ],
10
+ artifacts: [
11
+ junit: 'artifacts/rspec/**/*.xml',
12
+ html : [
13
+ 'Code Coverage': 'artifacts/rcov',
14
+ 'RuboCop' : 'artifacts/rubocop'
15
+ ],
16
+ raw : ['artifacts/**/*.gem']
17
+ ]
18
+ )
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ # The MIT License (MIT)
2
+
3
+ Copyright © 2022 The Regents of the University of California
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a
6
+ copy of this software and associated documentation files (the “Software”),
7
+ to deal in the Software without restriction, including without limitation
8
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
+ and/or sell copies of the Software, and to permit persons to whom the
10
+ Software is furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # BerkeleyLibrary::Alma
2
+
3
+ A utility gem for working with Alma / Primo.
4
+
5
+ ## Configuration
6
+
7
+ The `BerkeleyLibrary::Alma::Config` class includes the options below. These
8
+ can be read automatically from a Rails configuration
9
+ (`Rails.application.config.alma_sru_host = "..."`, etc.) or set directly
10
+ (`BerkeleyLibrary::Alma::Config.alma_sru_host = "..."`).
11
+
12
+ Alternatively, `BerkeleyLibrary::Alma::Config.default!` will set the
13
+ options to either:
14
+
15
+ 1. the value of the corresponding environment variable, if set, or
16
+ 2. the default value for the UC Berkeley Library.
17
+
18
+ | Option | Environment variable | Purpose | Berkeley default |
19
+ | --- | --- | --- | --- |
20
+ | `alma_sru_host` | `LIT_ALMA_SRU_HOST` | the Alma SRU hostname | `berkeley.alma.exlibrisgroup.com` |
21
+ | `alma_institution_code` | `LIT_ALMA_INSTITUTION_CODE` | the Alma institution code | `search.library.berkeley.edu` |
22
+ | `alma_primo_host` | `LIT_ALMA_PRIMO_HOST` | the Alma Primo host | `01UCS_BER` |
23
+ | `alma_permalink_key` | `LIT_ALMA_PERMALINK_KEY` | the Alma [permalink key](https://knowledge.exlibrisgroup.com/Primo/Knowledge_Articles/What_is_the_key_in_short_permalinks%3F) | `iqob43` |
24
+
25
+ ## Retrieving Alma records
26
+
27
+ The [`RecordId`](lib/berkeley_library/alma/record_id.rb) class encapsulates
28
+ an ID that can be used to look up records in Alma via
29
+ [SRU](https://developers.exlibrisgroup.com/alma/integrations/sru/).
30
+ This can be either an Alma MMS ID:
31
+
32
+ ```ruby
33
+ mms_id_str = '991054360089706532'
34
+ record_id = BerkeleyLibrary::Alma::RecordId.parse(mms_id_str)
35
+ # => #<BerkeleyLibrary::Alma::MMSID:0x0000000138949830 @institution="6532", @mms_id="991054360089706532", @type_prefix="99", @unique_part="105436008970">
36
+ ```
37
+
38
+ Or a Millennium bib number:
39
+
40
+ ```ruby
41
+ bib_number_str = 'b11082434'
42
+ record_id = BerkeleyLibrary::Alma::RecordId.parse(bib_number_str)
43
+ # => #<BerkeleyLibrary::Alma::BibNumber:0x0000000118815038 @check_str="9", @digit_str="11082434">
44
+ ```
45
+
46
+ Given a `RecordId` object, you can get the SRU query URI for the corresponding MARC record:
47
+
48
+ ```ruby
49
+ record_id.marc_uri
50
+ # => #<URI::HTTPS https://berkeley.alma.exlibrisgroup.com/view/sru/01UCS_BER?version=1.2&operation=searchRetrieve&query=alma.mms_id%3D991054360089706532>
51
+ ```
52
+
53
+ Or the MARC XML as a string:
54
+
55
+ ```ruby
56
+ marc_xml_str = record_id.get_marc_xml
57
+ # => "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><searchRetrieveResponse>...</searchRetrieveResponse>"
58
+ ```
59
+
60
+ Or just a [ruby-marc](https://github.com/ruby-marc/ruby-marc) `MARC::Record` object:
61
+
62
+ ```ruby
63
+ marc_record = record_id.get_marc_record
64
+ # => #<MARC::Record:0x0000000138b45490
65
+ ```
66
+
67
+ #### Calculating the check digit for a Millennium bib
68
+
69
+ You can also use `RecordId` to verify or calculate the check digit for a Millennium bib.
70
+
71
+ (Check digit calculation is based on the algorithm described in
72
+ "[Recipe: Computing the Millennium checkdigit](http://liwong.blogspot.com/2018/04/recipe-computing-millennium-checkdigit.html)"
73
+ by Lisa Wong of the McHenry Library, UC Santa Cruz.
74
+
75
+ ##### Calculating the check digit
76
+
77
+ The check digit will be appended to bib numbers without one,
78
+ or with the wildcard check digit `a`.
79
+
80
+ ```ruby
81
+ bib_number_str = 'b11082434'
82
+ record_id = BerkeleyLibrary::Alma::RecordId.parse(bib_number_str)
83
+ # => #<BerkeleyLibrary::Alma::BibNumber:0x0000000118815038 @check_str="9", @digit_str="11082434">
84
+ record_id.check_str
85
+ # => "9"
86
+ record_id.full_bib
87
+ # => "b110824349"
88
+
89
+ bib_number_str = 'b11082434a'
90
+ record_id = BerkeleyLibrary::Alma::RecordId.parse(bib_number_str)
91
+ # => #<BerkeleyLibrary::Alma::BibNumber:0x0000000118815038 @check_str="9", @digit_str="11082434">
92
+ ```
93
+
94
+ ##### Verifying the check digit
95
+
96
+ The `RecordId#parse` method will raise an error if passed a bib with a bad
97
+ check digit.
98
+
99
+ ```ruby
100
+ bib_number_str = 'b110824341' # wrong check digit; should be 9, not 2
101
+ # bib_number.rb:78:in `ensure_check_digit': 110824341 check digit invalid: expected 9, got 1 (ArgumentError)
102
+ # from /Users/david/Work/BerkeleyLibrary/alma/lib/berkeley_library/alma/bib_number.rb:68:in `split_bib'
103
+ # from /Users/david/Work/BerkeleyLibrary/alma/lib/berkeley_library/alma/bib_number.rb:27:in `initialize'
104
+ # from /Users/david/Work/BerkeleyLibrary/alma/lib/berkeley_library/alma/record_id.rb:35:in `new'
105
+ # from /Users/david/Work/BerkeleyLibrary/alma/lib/berkeley_library/alma/record_id.rb:35:in `parse'
106
+ ```
107
+
108
+ ## Scripts
109
+
110
+ ### `alma-mms-lookup`: Control field 001 record ID lookup
111
+
112
+ The `alma-mms-lookup` script takes one or more record IDs (either Millennium bib
113
+ numbers or Alma MMS IDs) and attempts to read the corresponding MARC records via
114
+ [SRU](https://developers.exlibrisgroup.com/alma/integrations/sru/) and extract
115
+ the canonical MMS ID for the record from the 001 control field.
116
+
117
+ #### Local execution
118
+
119
+ If you clone this repository and run `bundle install` from the project root,
120
+ you can run the `bin/alma-mms-lookup` script directly. Note that this requires
121
+ Ruby 3.x to be installed. (Alternatively, you can use Docker; see below.)
122
+
123
+ To look up a single ID:
124
+
125
+ ```sh
126
+ echo b11082434 | bin/alma-mms-lookup
127
+ ```
128
+
129
+ To look up a list of IDs given in a file `record-ids.txt`:
130
+
131
+ ```sh
132
+ bin/alma-mms-lookup < record-ids.txt
133
+ ```
134
+
135
+ #### Execution via Docker
136
+
137
+ To look up a single ID:
138
+
139
+ ```sh
140
+ echo b11082434 | docker compose run gem bin/alma-mms-lookup
141
+ ```
142
+
143
+ To look up a list of IDs given in a file `record-ids.txt`:
144
+
145
+ ```sh
146
+ docker compose run gem bin/alma-mms-lookup < record-ids.txt
147
+ ```
148
+
149
+ #### Output format
150
+
151
+ The output is tab-separated, in the form
152
+
153
+ ```none
154
+ <original bib number> <bib number with check digit> <MMS ID from 001>
155
+ ```
156
+
157
+ or
158
+
159
+ ```none
160
+ <orignal MMS id> <original MMS ID again> <MMS ID from 001>
161
+ ```
162
+
163
+ e.g.:
164
+
165
+ ```none
166
+ b11082434 b110824349 991038544199706532
167
+ 991038544199706532 991038544199706532 991038544199706532
168
+ ```
169
+
170
+ Any IDs that cannot be retrieved or parsed are left blank:
171
+
172
+ ```sh
173
+ echo 'b11082434
174
+ b1234
175
+ 991038544199706532
176
+ 9912348245906531
177
+ b110824349' | bin/alma-mms-lookup
178
+ ```
179
+
180
+ produces:
181
+
182
+ ```none
183
+ b11082434 b110824349 991038544199706532
184
+ b1234
185
+ 991038544199706532 991038544199706532 991038544199706532
186
+ [2022-01-03T14:17:09.060-08:00] WARN: GET https://berkeley.alma.exlibrisgroup.com/view/sru/01UCS_BER?version=1.2&operation=searchRetrieve&query=alma.mms_id%3D9912348245906531 did not return a MARC record
187
+ 9912348245906531 9912348245906531
188
+ b110824349 b110824349 991038544199706532
189
+ ```
190
+
191
+ Note that warning messages are written to STDOUT, so you may need to filter them
192
+ with `grep`:
193
+
194
+ ```sh
195
+ echo 'b11082434
196
+ b1234
197
+ 991038544199706532
198
+ 9912348245906531
199
+ b110824349' | bin/alma-mms-lookup | grep -v WARN
200
+ ```
201
+
202
+ produces:
203
+
204
+ ```none
205
+ b11082434 b110824349 991038544199706532
206
+ b1234
207
+ 991038544199706532 991038544199706532 991038544199706532
208
+ 9912348245906531 9912348245906531
209
+ b110824349 b110824349 991038544199706532
210
+ ```
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('Gemfile', __dir__)
2
+ require 'bundler/setup' # Set up gems listed in the Gemfile.
3
+
4
+ # ------------------------------------------------------------
5
+ # Application code
6
+
7
+ File.expand_path('lib', __dir__).tap do |lib|
8
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
9
+ end
10
+
11
+ # ------------------------------------------------------------
12
+ # CI
13
+
14
+ ENV['RAILS_ENV'] = 'test' if ENV['CI']
15
+
16
+ # ------------------------------------------------------------
17
+ # Custom tasks
18
+
19
+ desc 'Run tests, check test coverage, check code style, check for vulnerabilities, build gem'
20
+ task default: %i[coverage rubocop bundle:audit gem]