evergreen_holdings 0.4.0 → 0.5.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 +4 -4
- data/lib/evergreen_holdings.rb +232 -233
- data/lib/evergreen_holdings/errors.rb +2 -0
- data/lib/evergreen_holdings/idl_parser.rb +17 -0
- data/test/evergreen_holdings_test.rb +21 -21
- metadata +17 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b34258835d3686af2107f5ea96b6a3a95f2eca5dc4e19630fe1cc8fecce583d1
|
4
|
+
data.tar.gz: f285caa0b0a3cc693ad27a9b169c540dd3bc30f1cde438967d1b44971a6d97f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79564fcba394887f6efaeb9046a269a47796d14efc6def71771c22bce4852c6eec148c3e9ef92b4fa408461cde87fa407d2e1fd27e9d9ad4a1c46ea3c575dd90
|
7
|
+
data.tar.gz: defa58f9e2349386a241c9d70bef66764d74d37bc993fd3a09202a6803300e4bf6e9b8501781862e7f8424266a243668e3086d2632054b92f3accab4cd0db7cc
|
data/lib/evergreen_holdings.rb
CHANGED
@@ -1,233 +1,232 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'net/http'
|
4
|
-
require 'json'
|
5
|
-
require 'evergreen_holdings/errors'
|
6
|
-
require '
|
7
|
-
require '
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
#
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
@
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
#
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
@
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
@copies.push Item.new item_info
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
@
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
ou_id
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'json'
|
5
|
+
require 'evergreen_holdings/errors'
|
6
|
+
require 'evergreen_holdings/idl_parser'
|
7
|
+
require 'nokogiri'
|
8
|
+
require 'open-uri'
|
9
|
+
|
10
|
+
OSRF_PATH = '/osrf-gateway-v1'
|
11
|
+
|
12
|
+
module EvergreenHoldings
|
13
|
+
class Connection
|
14
|
+
attr_reader :org_units
|
15
|
+
|
16
|
+
# Create a new object with the evergreen_domain
|
17
|
+
# specified, e.g. http://libcat.linnbenton.edu
|
18
|
+
#
|
19
|
+
# Usage: `conn = EvergreenHoldings::Connection.new 'http://gapines.org'`
|
20
|
+
def initialize(evergreen_domain)
|
21
|
+
@evergreen_domain = evergreen_domain
|
22
|
+
@gateway = URI evergreen_domain + OSRF_PATH
|
23
|
+
@acpl_cache = {}
|
24
|
+
fetch_idl_order
|
25
|
+
raise CouldNotConnectToEvergreenError unless fetch_statuses
|
26
|
+
|
27
|
+
fetch_ou_tree
|
28
|
+
end
|
29
|
+
|
30
|
+
# Fetch holdings data from the Evergreen server
|
31
|
+
# Returns a Status object
|
32
|
+
#
|
33
|
+
# Usage: `stat = conn.get_holdings 23405`
|
34
|
+
# If you just want holdings at a specific org_unit: `my_connection.get_holdings 23405, org_unit: 5`
|
35
|
+
def get_holdings(tcn, options = {})
|
36
|
+
if options.key?(:org_unit)
|
37
|
+
if options[:descendants]
|
38
|
+
params = "format=json&input_format=json&service=open-ils.cat&method=open-ils.cat.asset.copy_tree.retrieve¶m=auth_token_not_needed_for_this_call¶m=#{tcn}"
|
39
|
+
@org_units[options[:org_unit]][:descendants]&.each do |ou|
|
40
|
+
params << + "¶m=#{ou}"
|
41
|
+
end
|
42
|
+
else
|
43
|
+
params = "format=json&input_format=json&service=open-ils.cat&method=open-ils.cat.asset.copy_tree.retrieve¶m=auth_token_not_needed_for_this_call¶m=#{tcn}¶m=#{options[:org_unit]}"
|
44
|
+
end
|
45
|
+
else
|
46
|
+
params = "format=json&input_format=json&service=open-ils.cat&method=open-ils.cat.asset.copy_tree.global.retrieve¶m=auth_token_not_needed_for_this_call¶m=#{tcn}"
|
47
|
+
end
|
48
|
+
@gateway.query = params
|
49
|
+
|
50
|
+
res = send_query
|
51
|
+
return Status.new res.body, @idl_order, self if res
|
52
|
+
end
|
53
|
+
|
54
|
+
# Given an ID, returns a human-readable name
|
55
|
+
def location_name(id)
|
56
|
+
@acpl_cache.fetch(id) { |id| fetch_new_acpl(id) || id }
|
57
|
+
end
|
58
|
+
|
59
|
+
def status_name(id)
|
60
|
+
@possible_item_statuses[id]
|
61
|
+
end
|
62
|
+
|
63
|
+
def ou_name(id)
|
64
|
+
@org_units[id][:name]
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def add_ou_descendants(id, parent)
|
70
|
+
(@org_units[parent][:descendants] ||= []) << id
|
71
|
+
add_ou_descendants id, @org_units[parent][:parent] if @org_units[parent][:parent]
|
72
|
+
end
|
73
|
+
|
74
|
+
def take_info_from_ou_tree(o)
|
75
|
+
id = o[@idl_order[:aou]['id']]
|
76
|
+
@org_units[id] = {}
|
77
|
+
@org_units[id][:name] = o[@idl_order[:aou]['name']]
|
78
|
+
if o[@idl_order[:aou]['parent_ou']]
|
79
|
+
@org_units[id][:parent] = o[@idl_order[:aou]['parent_ou']]
|
80
|
+
add_ou_descendants id, o[@idl_order[:aou]['parent_ou']]
|
81
|
+
end
|
82
|
+
o[@idl_order[:aou]['children']].each do |p|
|
83
|
+
take_info_from_ou_tree p['__p']
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Given the ID of a shelving location, this method
|
88
|
+
# finds the name of the location, caches it, and
|
89
|
+
# returns it
|
90
|
+
def fetch_new_acpl(id)
|
91
|
+
params = "format=json&input_format=json&service=open-ils.circ&method=open-ils.circ.copy_location.retrieve¶m=#{id}"
|
92
|
+
@gateway.query = params
|
93
|
+
res = send_query
|
94
|
+
if res
|
95
|
+
data = JSON.parse(res.body)['payload'][0]
|
96
|
+
name = data['__p'][@idl_order[:acpl]['name']] unless data.key? 'stacktrace'
|
97
|
+
@acpl_cache[id] = name
|
98
|
+
return name if name
|
99
|
+
end
|
100
|
+
false
|
101
|
+
end
|
102
|
+
|
103
|
+
def send_query
|
104
|
+
begin
|
105
|
+
res = Net::HTTP.get_response(@gateway)
|
106
|
+
rescue Errno::ECONNREFUSED, Net::ReadTimeout
|
107
|
+
return nil
|
108
|
+
end
|
109
|
+
return res if res.is_a?(Net::HTTPSuccess)
|
110
|
+
|
111
|
+
nil
|
112
|
+
end
|
113
|
+
|
114
|
+
def fetch_idl_order
|
115
|
+
begin
|
116
|
+
idl = Nokogiri::XML(URI.parse("#{@evergreen_domain}/reports/fm_IDL.xml").open)
|
117
|
+
rescue Errno::ECONNREFUSED, Net::ReadTimeout, OpenURI::HTTPError
|
118
|
+
raise CouldNotConnectToEvergreenError
|
119
|
+
end
|
120
|
+
|
121
|
+
@idl_order = IDLParser.new(idl).field_order_by_class %i[acn acp acpl aou ccs circ]
|
122
|
+
end
|
123
|
+
|
124
|
+
def fetch_statuses
|
125
|
+
@possible_item_statuses = []
|
126
|
+
params = 'format=json&input_format=json&service=open-ils.search&method=open-ils.search.config.copy_status.retrieve.all'
|
127
|
+
@gateway.query = params
|
128
|
+
res = send_query
|
129
|
+
if res
|
130
|
+
stats = JSON.parse(res.body)['payload'][0]
|
131
|
+
stats.each do |stat|
|
132
|
+
@possible_item_statuses[stat['__p'][@idl_order[:ccs]['id']]] = stat['__p'][@idl_order[:ccs]['name']]
|
133
|
+
end
|
134
|
+
return true unless stats.empty?
|
135
|
+
end
|
136
|
+
false
|
137
|
+
end
|
138
|
+
|
139
|
+
def fetch_ou_tree
|
140
|
+
@org_units = {}
|
141
|
+
params = 'format=json&input_format=json&service=open-ils.actor&method=open-ils.actor.org_tree.retrieve'
|
142
|
+
@gateway.query = params
|
143
|
+
res = send_query
|
144
|
+
if res
|
145
|
+
raw_orgs = JSON.parse(res.body)['payload'][0]['__p']
|
146
|
+
take_info_from_ou_tree raw_orgs
|
147
|
+
return true unless @org_units.empty?
|
148
|
+
end
|
149
|
+
false
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Status objects represent all the holdings attached to a specific tcn
|
154
|
+
class Status
|
155
|
+
attr_reader :copies, :libraries
|
156
|
+
|
157
|
+
def initialize(json_data, idl_order, connection = nil)
|
158
|
+
@idl_order = idl_order
|
159
|
+
@connection = connection
|
160
|
+
@raw_data = JSON.parse(json_data)['payload'][0]
|
161
|
+
extract_copies
|
162
|
+
substitute_values_for_ids unless @connection.nil?
|
163
|
+
@available_copies = []
|
164
|
+
@next_copy_available = 'a date'
|
165
|
+
end
|
166
|
+
|
167
|
+
# Determines if any copies are available for your patrons
|
168
|
+
def any_copies_available?
|
169
|
+
@copies.each do |copy|
|
170
|
+
return true if copy.status.zero?
|
171
|
+
return true if copy.status == 'Available'
|
172
|
+
end
|
173
|
+
false
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
# Look through @raw_data and find the copies
|
179
|
+
def extract_copies
|
180
|
+
@copies = []
|
181
|
+
@raw_data.each do |vol|
|
182
|
+
next if vol['__p'][0].empty?
|
183
|
+
|
184
|
+
vol['__p'][0].each do |item|
|
185
|
+
item_info = {
|
186
|
+
barcode: item['__p'][@idl_order[:acp]['barcode']],
|
187
|
+
call_number: vol['__p'][@idl_order[:acn]['label']],
|
188
|
+
location: item['__p'][@idl_order[:acp]['location']],
|
189
|
+
status: item['__p'][@idl_order[:acp]['status']],
|
190
|
+
owning_lib: item['__p'][@idl_order[:acp]['circ_lib']]
|
191
|
+
}
|
192
|
+
if item['__p'][@idl_order[:acp]['circulations']].is_a? Array
|
193
|
+
begin
|
194
|
+
item_info[:due_date] =
|
195
|
+
item['__p'][@idl_order[:acp]['circulations']][0]['__p'][@idl_order[:circ]['due_date']]
|
196
|
+
rescue StandardError
|
197
|
+
end
|
198
|
+
@copies.push Item.new item_info
|
199
|
+
else
|
200
|
+
@copies.push Item.new item_info
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def substitute_values_for_ids
|
207
|
+
@libraries = @connection.org_units.clone
|
208
|
+
@libraries.each { |_key, lib| lib[:copies] = [] }
|
209
|
+
@copies.each do |copy|
|
210
|
+
copy.location = @connection.location_name copy.location if copy.location.is_a? Numeric
|
211
|
+
copy.status = @connection.status_name copy.status if copy.status.is_a? Numeric
|
212
|
+
next unless copy.owning_lib.is_a? Numeric
|
213
|
+
|
214
|
+
ou_id = copy.owning_lib
|
215
|
+
copy.owning_lib = @connection.ou_name copy.owning_lib
|
216
|
+
@libraries[ou_id][:copies].push copy
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# A physical copy of an item
|
222
|
+
class Item
|
223
|
+
attr_accessor :location, :status, :owning_lib
|
224
|
+
attr_reader :barcode, :call_number, :due_date
|
225
|
+
|
226
|
+
def initialize(data = {})
|
227
|
+
data.each do |k, v|
|
228
|
+
instance_variable_set("@#{k}", v) unless v.nil?
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literals: true
|
2
|
+
|
3
|
+
module EvergreenHoldings
|
4
|
+
class IDLParser
|
5
|
+
def initialize(idl)
|
6
|
+
@idl = idl
|
7
|
+
end
|
8
|
+
|
9
|
+
def field_order_by_class(classes)
|
10
|
+
classes.map do |idl_class|
|
11
|
+
fields = @idl.xpath("//idl:class[@id='#{idl_class}']/idl:fields/idl:field", 'idl' => 'http://opensrf.org/spec/IDL/base/v1')
|
12
|
+
.map.with_index { |field, index| [field['name'], index] }
|
13
|
+
[idl_class, fields.to_h]
|
14
|
+
end.to_h
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,21 +1,21 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'evergreen_holdings'
|
3
|
+
|
4
|
+
class EvergreenHoldingsTest < Minitest::Test
|
5
|
+
def test_connecting_to_eg_returns_a_connection_object
|
6
|
+
conn = EvergreenHoldings::Connection.new 'https://gapines.org'
|
7
|
+
assert_instance_of EvergreenHoldings::Connection, conn
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_connecting_to_a_404_throws_an_error
|
11
|
+
assert_raises(CouldNotConnectToEvergreenError) do
|
12
|
+
EvergreenHoldings::Connection.new('http://httpstat.us/404')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_connecting_to_a_non_evergreen_server_throws_an_error
|
17
|
+
assert_raises(CouldNotConnectToEvergreenError) do
|
18
|
+
EvergreenHoldings::Connection.new('http://libfind.linnbenton.edu')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: evergreen_holdings
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jane Sandberg
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
14
15
|
requirement: !ruby/object:Gem::Requirement
|
15
16
|
requirements:
|
16
17
|
- - "~>"
|
17
18
|
- !ruby/object:Gem::Version
|
18
19
|
version: '1.11'
|
19
|
-
name: nokogiri
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -25,34 +25,35 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.11'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
28
29
|
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
31
|
- - "~>"
|
31
32
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.
|
33
|
-
name: coveralls
|
33
|
+
version: 5.0.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
40
|
+
version: 5.0.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
42
43
|
requirement: !ruby/object:Gem::Requirement
|
43
44
|
requirements:
|
44
|
-
- - "
|
45
|
+
- - ">="
|
45
46
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
47
|
-
name: minitest
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
56
57
|
requirement: !ruby/object:Gem::Requirement
|
57
58
|
requirements:
|
58
59
|
- - ">"
|
@@ -61,7 +62,6 @@ dependencies:
|
|
61
62
|
- - "<"
|
62
63
|
- !ruby/object:Gem::Version
|
63
64
|
version: '2'
|
64
|
-
name: rubocop
|
65
65
|
type: :development
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -80,12 +80,13 @@ extra_rdoc_files: []
|
|
80
80
|
files:
|
81
81
|
- lib/evergreen_holdings.rb
|
82
82
|
- lib/evergreen_holdings/errors.rb
|
83
|
+
- lib/evergreen_holdings/idl_parser.rb
|
83
84
|
- test/evergreen_holdings_test.rb
|
84
85
|
homepage: https://github.com/sandbergja/evergreen_holdings_gem
|
85
86
|
licenses:
|
86
87
|
- MIT
|
87
88
|
metadata: {}
|
88
|
-
post_install_message:
|
89
|
+
post_install_message:
|
89
90
|
rdoc_options: []
|
90
91
|
require_paths:
|
91
92
|
- lib
|
@@ -100,8 +101,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
101
|
- !ruby/object:Gem::Version
|
101
102
|
version: '0'
|
102
103
|
requirements: []
|
103
|
-
rubygems_version: 3.0.
|
104
|
-
signing_key:
|
104
|
+
rubygems_version: 3.0.3
|
105
|
+
signing_key:
|
105
106
|
specification_version: 4
|
106
107
|
summary: A ruby gem for getting information about copy availability from Evergreen
|
107
108
|
ILS
|