berkeley_library-alma 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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]