pennmarc 1.2.5 → 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21463a3d231e3ba853929bc03241d8e3c109c6191d3a5747c1a397aad40e454d
4
- data.tar.gz: e747a26ee6ed508b13a3079acd2291d194d4a9a9bc4a984dcefd8145d5f76084
3
+ metadata.gz: bc89ffad46c996296dc5cd84d8a2b9c81b82653b24c9d16f6aa9e12c9c3c6aaa
4
+ data.tar.gz: 5e1f488f73b07970e4242a7bbffb1536db2f800e73db72d4ad9b33d75375ad38
5
5
  SHA512:
6
- metadata.gz: ee0a42b85b4862caca7417176947497d63253d07818341e3ef483789554dfcf06eff4f658a89d44d865e7354f4dcae3e88e060cdd41c941e016de5d86e8ad365
7
- data.tar.gz: ca200369654cb607e14ea1225ce785a90ca05da9f5fe9a3a7390748b997b4b5e423f26a1c832bfab14c339a493af39f2422171b647542f92a926e5c2a7405993
6
+ metadata.gz: 61a8aded7159b786a45213d03c4eb17b60eced7dba21e79b8b634a03bccdcd7f1e312f5205431e3215a95fbdba91ad60611312a03939f3c03bfc39b85dc5dc88
7
+ data.tar.gz: 756c4a538eedd1fd7b9bc12a347547863ea8674965c3a87669a32ca39d3c50724af0a17e3d1747e7e3a06385a9c6b55aead58d8c5d091996af5c37ed1c1641ba
data/Gemfile CHANGED
@@ -3,6 +3,7 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gem 'activesupport', '~> 7'
6
+ gem 'lcsort'
6
7
  gem 'library_stdnums', '~> 1.6'
7
8
  gem 'marc', '~> 1.2'
8
9
  gem 'nokogiri', '~> 1.15'
data/Gemfile.lock CHANGED
@@ -13,6 +13,7 @@ GEM
13
13
  i18n (1.13.0)
14
14
  concurrent-ruby (~> 1.0)
15
15
  json (2.6.3)
16
+ lcsort (0.9.1)
16
17
  library_stdnums (1.6.0)
17
18
  marc (1.2.0)
18
19
  rexml
@@ -111,6 +112,7 @@ PLATFORMS
111
112
 
112
113
  DEPENDENCIES
113
114
  activesupport (~> 7)
115
+ lcsort
114
116
  library_stdnums (~> 1.6)
115
117
  marc (~> 1.2)
116
118
  nokogiri (~> 1.15)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'lcsort'
4
+
3
5
  module PennMARC
4
6
  # Generates library of congress and dewey classifications using call number data.
5
7
  class Classification < Helper
@@ -42,26 +44,53 @@ module PennMARC
42
44
  }.uniq
43
45
  end
44
46
 
47
+ # Return a normalized Call Number value for sorting purposes. This uses the Lcsort gem normalization logic, which
48
+ # returns nil for non-LC call numbers. For now, this returns only the call number values from the enrichment
49
+ # inventory fields.
50
+ # @note this could be made more efficient by just returning the first value, but in the future we may want to be
51
+ # more discerning about which call number we return (longest?)
52
+ # @param record [MARC::Record]
53
+ # @return [String, nil] a normalized call number
54
+ def sort(record)
55
+ values(record, loc_only: true).filter_map { |val| Lcsort.normalize(val) }.first
56
+ end
57
+
45
58
  # Parse call number values from inventory fields, including both hld and itm fields from publishing enrichment.
46
59
  # Return only unique values.
47
60
  # @param record [MARC::Record]
48
61
  # @return [Array<String>] array of call numbers from inventory fields
49
62
  def call_number_search(record)
63
+ values(record, loc_only: false)
64
+ end
65
+
66
+ # Return raw call number values from inventory fields
67
+ # @param record [MARC::Record]
68
+ # @param loc_only [Boolean] whether or not to explicitly return only LOC call numbers from ITM & AVA inventory
69
+ # @return [Array<String>]
70
+ def values(record, loc_only:)
50
71
  call_nums = record.fields(TAGS).filter_map do |field|
72
+ next if loc_only && !loc_call_number_type?(subfield_values(field, call_number_type_sf(field))&.first)
73
+
51
74
  subfield_values(field, call_number_sf(field))
52
75
  end
53
76
 
54
- # Ensure we get call numbers for records with no `itm` tags by also checking `hld` and de-duping
55
- call_nums += record.fields([Enriched::Pub::PHYS_INVENTORY_TAG]).filter_map do |field|
77
+ call_nums += hld_field_call_nums(record)
78
+ call_nums.flatten.uniq
79
+ end
80
+
81
+ private
82
+
83
+ # Get call nums from `hld` tags. Useful if no call nums are available from `itm` tags
84
+ # @param record [MARC::Record]
85
+ # @return [Array<String>]
86
+ def hld_field_call_nums(record)
87
+ record.fields([Enriched::Pub::PHYS_INVENTORY_TAG]).filter_map do |field|
56
88
  first = subfield_values(field, Enriched::Pub::HOLDING_CLASSIFICATION_PART)&.first
57
89
  last = subfield_values(field, Enriched::Pub::HOLDING_ITEM_PART)&.first
58
90
  "#{first} #{last}".squish.presence
59
91
  end
60
- call_nums.flatten.uniq
61
92
  end
62
93
 
63
- private
64
-
65
94
  # Retrieve subfield code that stores the call number on enriched marc field
66
95
  # @param field [MARC::DataField]
67
96
  # @return [String]
@@ -106,10 +135,10 @@ module PennMARC
106
135
  end
107
136
 
108
137
  # Determine whether call number type is library of congress
109
- # @param call_number_type [String] value from call number type subfield
138
+ # @param call_number_type [String, nil] value from call number type subfield
110
139
  # @return [Boolean]
111
140
  def loc_call_number_type?(call_number_type)
112
- call_number_type == '0'
141
+ call_number_type == LOC_CALL_NUMBER_TYPE
113
142
  end
114
143
  end
115
144
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PennMARC
4
- VERSION = '1.2.5'
4
+ VERSION = '1.2.6'
5
5
  end
data/pennmarc.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.required_ruby_version = '>= 3.2'
20
20
 
21
21
  s.add_dependency 'activesupport', '~> 7'
22
+ s.add_dependency 'lcsort', '~> 0.9'
22
23
  s.add_dependency 'library_stdnums', '~> 1.6'
23
24
  s.add_dependency 'marc', '~> 1.2'
24
25
  s.add_dependency 'nokogiri', '~> 1.15'
@@ -43,6 +43,86 @@ describe 'PennMARC::Classification' do
43
43
  end
44
44
  end
45
45
 
46
+ describe '.sort' do
47
+ context 'with enrichment via the Alma publishing process and no valid call number' do
48
+ let(:fields) do
49
+ [marc_field(tag: PennMARC::Enriched::Pub::ITEM_TAG, subfields: {
50
+ PennMARC::Enriched::Pub::ITEM_CALL_NUMBER_TYPE => helper::LOC_CALL_NUMBER_TYPE,
51
+ PennMARC::Enriched::Pub::ITEM_CALL_NUMBER => 'Secret Drawer Copy'
52
+ }),
53
+ marc_field(tag: PennMARC::Enriched::Pub::ITEM_TAG, subfields: {
54
+ PennMARC::Enriched::Pub::ITEM_CALL_NUMBER_TYPE => helper::DEWEY_CALL_NUMBER_TYPE,
55
+ PennMARC::Enriched::Pub::ITEM_CALL_NUMBER => '691.3 B2141'
56
+ })]
57
+ end
58
+
59
+ it 'returns nil' do
60
+ expect(helper.sort(record)).to be_nil
61
+ end
62
+ end
63
+
64
+ context 'with enrichment via the Alma publishing process and itm fields' do
65
+ let(:fields) do
66
+ [marc_field(tag: PennMARC::Enriched::Pub::ITEM_TAG, subfields: {
67
+ PennMARC::Enriched::Pub::ITEM_CALL_NUMBER_TYPE => helper::LOC_CALL_NUMBER_TYPE,
68
+ PennMARC::Enriched::Pub::ITEM_CALL_NUMBER => 'QL756 .S643'
69
+ }),
70
+ marc_field(tag: PennMARC::Enriched::Pub::ITEM_TAG, subfields: {
71
+ PennMARC::Enriched::Pub::ITEM_CALL_NUMBER_TYPE => helper::LOC_CALL_NUMBER_TYPE,
72
+ PennMARC::Enriched::Pub::ITEM_CALL_NUMBER => 'Secret Drawer Copy'
73
+ }),
74
+ marc_field(tag: PennMARC::Enriched::Pub::ITEM_TAG, subfields: {
75
+ PennMARC::Enriched::Pub::ITEM_CALL_NUMBER_TYPE => helper::DEWEY_CALL_NUMBER_TYPE,
76
+ PennMARC::Enriched::Pub::ITEM_CALL_NUMBER => '691.3 B2141'
77
+ })]
78
+ end
79
+
80
+ it 'returns a normalized version of the first valid call number' do
81
+ expect(helper.sort(record)).to eq 'QL.0756.S643'
82
+ end
83
+ end
84
+
85
+ context 'with enrichment via the Alma publishing process including both hld and itm fields' do
86
+ let(:fields) do
87
+ [marc_field(tag: PennMARC::Enriched::Pub::ITEM_TAG,
88
+ subfields: { PennMARC::Enriched::Pub::ITEM_CALL_NUMBER_TYPE => helper::LOC_CALL_NUMBER_TYPE,
89
+ PennMARC::Enriched::Pub::ITEM_CALL_NUMBER => 'QL756 .S643 1989' }),
90
+ marc_field(tag: PennMARC::Enriched::Pub::PHYS_INVENTORY_TAG,
91
+ subfields: { PennMARC::Enriched::Pub::HOLDING_CLASSIFICATION_PART => 'QL756',
92
+ PennMARC::Enriched::Pub::HOLDING_ITEM_PART => '.S643' })]
93
+ end
94
+
95
+ it 'returns a normalized version of the first valid call number' do
96
+ expect(helper.sort(record)).to eq 'QL.0756.S643.1989'
97
+ end
98
+ end
99
+
100
+ context 'with enrichment via the Alma publishing process and only hld fields' do
101
+ let(:fields) do
102
+ [marc_field(tag: PennMARC::Enriched::Pub::PHYS_INVENTORY_TAG,
103
+ subfields: { PennMARC::Enriched::Pub::HOLDING_CLASSIFICATION_PART => 'KF6450',
104
+ PennMARC::Enriched::Pub::HOLDING_ITEM_PART => '.C59 1989' })]
105
+ end
106
+
107
+ it 'returns expected normalized value' do
108
+ expect(helper.sort(record)).to eq 'KF.6450.C59.1989'
109
+ end
110
+ end
111
+
112
+ context 'with enrichment with availability info via Alma Api' do
113
+ let(:fields) do
114
+ [marc_field(tag: PennMARC::Enriched::Api::PHYS_INVENTORY_TAG, subfields: {
115
+ PennMARC::Enriched::Api::PHYS_CALL_NUMBER_TYPE => helper::LOC_CALL_NUMBER_TYPE,
116
+ PennMARC::Enriched::Api::PHYS_CALL_NUMBER => 'QL756 .S643'
117
+ })]
118
+ end
119
+
120
+ it 'returns expected normalized value' do
121
+ expect(helper.sort(record)).to eq 'QL.0756.S643'
122
+ end
123
+ end
124
+ end
125
+
46
126
  describe '.call_number_search' do
47
127
  let(:fields) do
48
128
  [marc_field(tag: config[:tag],
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pennmarc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Kanning
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2024-12-17 00:00:00.000000000 Z
15
+ date: 2024-12-20 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activesupport
@@ -28,6 +28,20 @@ dependencies:
28
28
  - - "~>"
29
29
  - !ruby/object:Gem::Version
30
30
  version: '7'
31
+ - !ruby/object:Gem::Dependency
32
+ name: lcsort
33
+ requirement: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - "~>"
36
+ - !ruby/object:Gem::Version
37
+ version: '0.9'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - "~>"
43
+ - !ruby/object:Gem::Version
44
+ version: '0.9'
31
45
  - !ruby/object:Gem::Dependency
32
46
  name: library_stdnums
33
47
  requirement: !ruby/object:Gem::Requirement