high_level_browse 1.0.0 → 1.1.0

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: 5eae24ef8906dfb25f1f949b4b29b69a33834dc63a7b0d96cd356324b14a79df
4
- data.tar.gz: 919434516a5098b1c4f9766434c68b7b7e6960128a0eb59abc7e442da520de5e
3
+ metadata.gz: a9724032a385683374e08526620f1588020ca677e8e55e828c95fb9ba8518dd4
4
+ data.tar.gz: 95a7ce1130b8eec58ab9b87532c1da8c388d64bc407fb51fa4679907a172e7ab
5
5
  SHA512:
6
- metadata.gz: 5aa8cb1cb8472c788c1def8efff185a8fc16957ef97450178687941f6dc5a03444f6d85b1c25f601aa34eef02ed51e8ab7475c9d067e2db35aa94118d319a7dc
7
- data.tar.gz: 390752555d91aec5060be2a34097b9cc6ca664b22c44ae6b29a989e9cb766bc45b83599310d2fec2ee79fe3155678c41fc52c24f6a3658692ab7b2ac32bb513d
6
+ metadata.gz: b17ebd104a06a41e8ccef38cd6afff6eca424ed32ffba94b678e1dd21f3ce1c0b13946d69851e23af6b3be4d710d456199d8478e29e9f2699a2f1e46d2ffcf0a
7
+ data.tar.gz: 8b2c9b47c394f530db121898f9c4199eb6f3dfd9d74806aedc80264d40bb5f009235b851b7827bbd2629766acaa587258175fee93534112eccc6c158cdfcce41
@@ -0,0 +1,38 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ "main" ]
13
+ pull_request:
14
+ branches: [ "main" ]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ test:
21
+
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ matrix:
25
+ ruby-version: ['2.7', '3.0', '3.1', jruby]
26
+
27
+ steps:
28
+ - uses: actions/checkout@v3
29
+ - name: Set up Ruby
30
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
31
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
32
+ # uses: ruby/setup-ruby@v1
33
+ uses: ruby/setup-ruby@2b019609e2b0f1ea1a2bc8ca11cb82ab46ada124
34
+ with:
35
+ ruby-version: ${{ matrix.ruby-version }}
36
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
37
+ - name: Run tests
38
+ run: bundle exec rake spec
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # High Level Browse
2
2
 
3
+ ## 1.1.0
4
+
5
+ Change code to deal with new UMich XML format
6
+
3
7
  ## 1.0.0
4
8
 
5
9
  * New normalization algorithm.
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in high_level_browse.gemspec
4
4
  gemspec
data/Rakefile CHANGED
@@ -1,9 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
- require "rake/testtask"
2
+ require "rspec/core/rake_task"
3
3
 
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- end
7
-
8
- task :default => :test
4
+ RSpec::Core::RakeTask.new(:spec)
9
5
 
6
+ task :default => :spec
@@ -1,25 +1,26 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path("../lib", __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'high_level_browse/version'
3
+ require "high_level_browse/version"
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "high_level_browse"
8
- spec.version = HighLevelBrowse::VERSION
9
- spec.authors = ["Bill Dueber"]
10
- spec.email = ["bill@dueber.com"]
11
- spec.summary = %q{Map LC call numbers to academic categories.}
6
+ spec.name = "high_level_browse"
7
+ spec.version = HighLevelBrowse::VERSION
8
+ spec.authors = ["Bill Dueber"]
9
+ spec.email = ["bill@dueber.com"]
10
+ spec.summary = "Map LC call numbers to academic categories."
12
11
  spec.homepage = ""
13
- spec.license = "MIT"
12
+ spec.license = "MIT"
14
13
 
15
- spec.files = `git ls-files -z`.split("\x0")
16
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
17
  spec.require_paths = ["lib"]
19
18
 
20
- spec.add_dependency 'nokogiri', '~>1.0'
19
+ spec.add_dependency "nokogiri", "~>1.0"
21
20
 
22
- spec.add_development_dependency "bundler", '~>2.0'
21
+ spec.add_development_dependency "bundler", "~>2.0"
23
22
  spec.add_development_dependency "rake"
24
- spec.add_development_dependency "minitest"
23
+ spec.add_development_dependency "rspec", "~>3.0"
24
+ spec.add_development_dependency "standard"
25
+ spec.add_development_dependency "pry"
25
26
  end
@@ -1,9 +1,10 @@
1
- require 'high_level_browse/range_tree'
1
+ # frozen_string_literal: true
2
+
3
+ require "high_level_browse/range_tree"
2
4
 
3
5
  # An efficient set of CallNumberRanges from which to get topics
4
6
  class HighLevelBrowse::CallNumberRangeSet < HighLevelBrowse::RangeTree
5
-
6
- ANY_DIGIT = /\d/.freeze
7
+ ANY_DIGIT = /\d/
7
8
 
8
9
  def has_digits(str)
9
10
  ANY_DIGIT.match?(str)
@@ -14,9 +15,9 @@ class HighLevelBrowse::CallNumberRangeSet < HighLevelBrowse::RangeTree
14
15
  # @return [Array<Array<String>>] Arrays of topic labels
15
16
  def topics_for(raw_lc)
16
17
  normalized = ::HighLevelBrowse::CallNumberRange.callnumber_normalize(raw_lc)
17
- self.search(normalized).map(&:topic_array).uniq
18
+ search(normalized).map(&:topic_array).uniq
18
19
  rescue => e
19
- require 'pry'; binding.pry
20
+ raise "Error getting topics for '#{raw_lc}': #{e}"
20
21
  end
21
22
  end
22
23
 
@@ -57,7 +58,7 @@ class HighLevelBrowse::CallNumberRange
57
58
 
58
59
  # Normalize the callnumber in a slightly more sane way
59
60
  # @param [String] cn The raw callnumber to normalize
60
- CN = /\A\s*(?<letters>\p{L}{1,3})\s*(?<digits>\d{1,5}(?!\d))(?:\.(?<decimals>\d+))?(?<rest>.*)\Z/.freeze
61
+ CN = /\A\s*(?<letters>\p{L}{1,3})\s*(?<digits>\d{1,5}(?!\d))(?:\.(?<decimals>\d+))?(?<rest>.*)\Z/
61
62
 
62
63
  def self.callnumber_normalize(cs_str)
63
64
  return nil if cs_str.nil?
@@ -72,7 +73,7 @@ class HighLevelBrowse::CallNumberRange
72
73
  decimals = m[:decimals] ? "." + m[:decimals] : ""
73
74
  rest = cleanup_freetext(m[:rest])
74
75
  clean = m[:letters] + digits + decimals + " " + rest
75
- clean.strip.gsub(/\s+/, ' ')
76
+ clean.strip.gsub(/\s+/, " ")
76
77
  end
77
78
 
78
79
  # @param [String] str String to clean up
@@ -85,11 +86,11 @@ class HighLevelBrowse::CallNumberRange
85
86
  s = replace_dot_before_letter_with_space(s)
86
87
  s = remove_dots_between_letters(s)
87
88
  s = force_space_between_digit_and_letter(s)
88
- s.strip.gsub(/\s+/, ' ')
89
+ s.strip.gsub(/\s+/, " ")
89
90
  end
90
91
 
91
92
  def self.replace_dot_before_letter_with_space(s)
92
- s.gsub /\.(\p{L})/, '\\1'
93
+ s.gsub(/\.(\p{L})/, '\\1')
93
94
  end
94
95
 
95
96
  # @param [String] str
@@ -112,12 +113,12 @@ class HighLevelBrowse::CallNumberRange
112
113
 
113
114
  # Compare based on @min, then end
114
115
  # @param [CallNumberRange] o the range to compare to
115
- def <=>(o)
116
- [self.min, self.max] <=> [o.min, o.max]
116
+ def <=>(other)
117
+ [min, max] <=> [other.min, other.max]
117
118
  end
118
119
 
119
120
  def to_s
120
- "[#{self.min_raw} - #{self.max_raw}]"
121
+ "[#{min_raw} - #{max_raw}]"
121
122
  end
122
123
 
123
124
  def reconstitute(min, max, min_raw, max_raw, firstletter, topic_array)
@@ -139,14 +140,13 @@ class HighLevelBrowse::CallNumberRange
139
140
  # @nodoc
140
141
  # JSON roundtrip
141
142
  def to_json(*a)
142
- {'json_class' => self.class.name, 'data' => [@min, @max, @min_raw, @max_raw, @firstletter, @topic_array]
143
- }.to_json(*a)
143
+ {"json_class" => self.class.name, "data" => [@min, @max, @min_raw, @max_raw, @firstletter, @topic_array]}.to_json(*a)
144
144
  end
145
145
 
146
146
  # @nodoc
147
147
  def self.json_create(h)
148
- cnr = self.allocate
149
- cnr.reconstitute(*(h['data']))
148
+ cnr = allocate
149
+ cnr.reconstitute(*(h["data"]))
150
150
  cnr
151
151
  end
152
152
 
@@ -158,7 +158,8 @@ class HighLevelBrowse::CallNumberRange
158
158
  if possible_min.nil? # didn't normalize
159
159
  @illegal = true
160
160
  nil
161
- else @min = possible_min
161
+ else
162
+ @min = possible_min
162
163
  end
163
164
  end
164
165
 
@@ -169,7 +170,8 @@ class HighLevelBrowse::CallNumberRange
169
170
  if possible_max.nil? # didn't normalize
170
171
  @illegal = true
171
172
  nil
172
- else @max = possible_max + '~' # add a tilde to make it a true endpoint
173
+ else
174
+ @max = possible_max + "~" # add a tilde to make it a true endpoint
173
175
  end
174
176
  end
175
177
 
@@ -187,5 +189,4 @@ class HighLevelBrowse::CallNumberRange
187
189
 
188
190
  alias_method :cover?, :contains
189
191
  alias_method :member?, :contains
190
-
191
192
  end
@@ -1,20 +1,21 @@
1
- require 'nokogiri'
2
- require 'high_level_browse/call_number_range'
3
- require 'zlib'
4
- require 'json'
1
+ # frozen_string_literal: true
5
2
 
6
- class HighLevelBrowse::DB
3
+ require "nokogiri"
4
+ require "high_level_browse/call_number_range"
5
+ require "zlib"
6
+ require "json"
7
7
 
8
+ class HighLevelBrowse::DB
8
9
  # Hard-code filename. If you need more than one, put them
9
10
  # in different directories
10
- FILENAME = 'hlb.json.gz'
11
+ FILENAME = "hlb.json.gz"
11
12
 
12
13
  # Given a bunch of CallNumberRange objects, create a new
13
14
  # database with an efficient structure for querying
14
15
  # @param [Array<HighLevelBrowse::CallNumberRange>] array_of_ranges
15
16
  def initialize(array_of_ranges)
16
17
  @all = array_of_ranges
17
- @ranges = self.create_letter_indexed_ranges(@all)
18
+ @ranges = create_letter_indexed_ranges(@all)
18
19
  end
19
20
 
20
21
  # Given an array of ranges, create efficient
@@ -22,7 +23,7 @@ class HighLevelBrowse::DB
22
23
  # @private
23
24
  def create_letter_indexed_ranges(all)
24
25
  bins = {}
25
- ('a'..'z').each do |letter|
26
+ ("a".."z").each do |letter|
26
27
  cnrs = all.find_all { |x| x.firstletter == letter }
27
28
  bins[letter] = HighLevelBrowse::CallNumberRangeSet.new(cnrs)
28
29
  end
@@ -41,12 +42,14 @@ class HighLevelBrowse::DB
41
42
  def topics(*raw_callnumber_strings)
42
43
  raw_callnumber_strings.reduce([]) do |acc, raw_callnumber_string|
43
44
  firstletter = if raw_callnumber_string.nil?
44
- nil
45
- else raw_callnumber_string.to_s.strip.downcase[0]
46
- end
45
+ nil
46
+ else
47
+ raw_callnumber_string.to_s.strip.downcase[0]
48
+ end
47
49
  if @ranges.has_key? firstletter
48
50
  acc + @ranges[firstletter].topics_for(raw_callnumber_string)
49
- else acc
51
+ else
52
+ acc
50
53
  end
51
54
  end.uniq
52
55
  end
@@ -61,7 +64,7 @@ class HighLevelBrowse::DB
61
64
  def self.new_from_xml(xml)
62
65
  noko_doc_root = Nokogiri::XML(xml)
63
66
  simple_array_of_cnrs = cnrs_within_noko_node(node: noko_doc_root)
64
- self.new(simple_array_of_cnrs).freeze
67
+ new(simple_array_of_cnrs).freeze
65
68
  end
66
69
 
67
70
  # Save to disk
@@ -78,9 +81,9 @@ class HighLevelBrowse::DB
78
81
  # @return [DB] The loaded database
79
82
  def self.load(dir:)
80
83
  simple_array_of_cnrs = Zlib::GzipReader.open(File.join(dir, FILENAME)) do |infile|
81
- JSON.load(infile.read).to_a
84
+ JSON.parse(infile.read, create_additions: true).to_a
82
85
  end
83
- db = self.new(simple_array_of_cnrs)
86
+ db = new(simple_array_of_cnrs)
84
87
  db.freeze
85
88
  db
86
89
  end
@@ -93,51 +96,54 @@ class HighLevelBrowse::DB
93
96
  self
94
97
  end
95
98
 
96
- private
97
-
98
- # Recurse through the parsed XML document, at each stage keeping track of
99
- # * where we are (what are the xpath children?)
100
- # * what the current topics are ([level1, level2])
101
- # Get all the call numbers assocaited with the topic represented by the given node,
102
- # as well as all the children of the given node, and send it back as a big ol' array
103
- # @param [Nokogiri::XML::Node] node A node of the parsed HLB XML file
104
- # @param [Array<String>] decendent_xpaths A list of xpaths to the decendents of this node
105
- # @param [Array<String>] topic_array An array with all levels of the topics associated with this node
106
- # @return [Array<HighLevelBrowse::CallNumberRange>]
107
- def self.cnrs_within_noko_node(node:, decendent_xpaths: ['/hlb/subject', 'topic', 'sub-topic'], topic_array: [])
108
- if decendent_xpaths.empty?
109
- [] # base case -- we're as low as we're going to go
110
- else current_xpath_component = decendent_xpaths[0]
111
- new_xpath = decendent_xpaths[1..-1]
112
- new_topic = topic_array.dup
113
- new_topic.push node[:name] unless node == node.document # skip the root
114
- cnrs = []
115
- # For each sub-component, get both the call-number-ranges (cnrs) assocaited
116
- # with this level, as well as recusively getting from all the children
117
- node.xpath(current_xpath_component).each do |c|
118
- cnrs += call_numbers_list_from_leaves(node: c, topic_array: new_topic)
119
- cnrs += cnrs_within_noko_node(node: c, decendent_xpaths: new_xpath, topic_array: new_topic)
120
- end
121
- cnrs
99
+ class << self
100
+ private
101
+
102
+ # Recurse through the parsed XML document, at each stage keeping track of
103
+ # * where we are (what are the xpath children?)
104
+ # * what the current topics are ([level1, level2])
105
+ # Get all the call numbers assocaited with the topic represented by the given node,
106
+ # as well as all the children of the given node, and send it back as a big ol' array
107
+ # @param [Nokogiri::XML::Node] node A node of the parsed HLB XML file
108
+ # @param [Array<String>] decendent_xpaths A list of xpaths to the decendents of this node
109
+ # @param [Array<String>] topic_array An array with all levels of the topics associated with this node
110
+ # @return [Array<HighLevelBrowse::CallNumberRange>]
111
+ def cnrs_within_noko_node(node:, decendent_xpaths: ["/hlb/subject", "topic"], topic_array: [])
112
+ if decendent_xpaths.empty?
113
+ [] # base case -- we're as low as we're going to go
114
+ else
115
+ current_xpath_component = decendent_xpaths[0]
116
+ new_xpath = decendent_xpaths[1..]
117
+ new_topic = topic_array.dup
118
+ new_topic.push node[:name] unless node == node.document # skip the root
119
+ cnrs = []
120
+ # For each sub-component, get both the call-number-ranges (cnrs) assocaited
121
+ # with this level, as well as recusively getting from all the children
122
+ node.xpath(current_xpath_component).each do |c|
123
+ cnrs += call_numbers_list_from_leaves(node: c, topic_array: new_topic)
124
+ cnrs += cnrs_within_noko_node(node: c, decendent_xpaths: new_xpath, topic_array: new_topic)
125
+ end
126
+ cnrs
127
+ end
122
128
  end
123
- end
124
-
125
- # Given a second-to-lowest-level node, get its topic and
126
- # extract call number ranges from its children
127
- def self.call_numbers_list_from_leaves(node:, topic_array:)
128
- cnrs = []
129
- new_topic = topic_array.dup.push node[:name]
130
- node.xpath('call-numbers').each do |cn_node|
131
- min = cn_node[:start]
132
- max = cn_node[:end]
133
129
 
134
- new_cnr = HighLevelBrowse::CallNumberRange.new(min: min, max: max, topic_array: new_topic)
135
- if new_cnr.illegal?
136
- # do some sort of logging else cnrs.push new_cnr
130
+ # Given a second-to-lowest-level node, get its topic and
131
+ # extract call number ranges from its children
132
+ def call_numbers_list_from_leaves(node:, topic_array:)
133
+ cnrs = []
134
+ new_topic = topic_array.dup.push node[:name]
135
+ node.xpath("call-numbers").each do |cn_node|
136
+ min = cn_node[:start]
137
+ max = cn_node[:end]
138
+
139
+ new_cnr = HighLevelBrowse::CallNumberRange.new(min: min, max: max, topic_array: new_topic)
140
+ if new_cnr.illegal?
141
+ # do some sort of logging else cnrs.push new_cnr
142
+ else
143
+ cnrs << new_cnr
144
+ end
137
145
  end
146
+ cnrs
138
147
  end
139
- cnrs
140
-
141
148
  end
142
-
143
149
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Never released as a gem, as near as I can tell.
2
4
  # Taken from https://github.com/clearhaus/range-tree,
3
5
  # which was released under the MIT license
@@ -10,11 +12,11 @@ module HighLevelBrowse
10
12
  class RangeTree
11
13
  class Node
12
14
  def initialize(left, range, right, min, max)
13
- @left = left
15
+ @left = left
14
16
  @range = range
15
17
  @right = right
16
- @min = min || range.min
17
- @max = max || range.max
18
+ @min = min || range.min
19
+ @max = max || range.max
18
20
  end
19
21
 
20
22
  attr_reader :left, :range, :right, :min, :max
@@ -26,7 +28,7 @@ module HighLevelBrowse
26
28
  # same left endpoint, then it's more efficient if also secondarily sorted by
27
29
  # the right endpoint (or equivalently by the length).
28
30
 
29
- @root = RangeTree.split(ranges.sort{|a,b| (a.min <=> b.min) || (a.max <=> b.max)})
31
+ @root = RangeTree.split(ranges.sort { |a, b| (a.min <=> b.min) || (a.max <=> b.max) })
30
32
  end
31
33
 
32
34
  attr_reader :root
@@ -34,17 +36,17 @@ module HighLevelBrowse
34
36
  def self.split(ranges)
35
37
  return nil if ranges.empty?
36
38
 
37
- middle = ranges.length/2
39
+ middle = ranges.length / 2
38
40
 
39
- left = split(ranges.slice(0, middle)) # Handle middle == 0 correctly.
41
+ left = split(ranges.slice(0, middle)) # Handle middle == 0 correctly.
40
42
  range = ranges[middle] # Current range.
41
- right = split(ranges[(middle+1)..-1]) # Handle middle == ranges.length correctly.
43
+ right = split(ranges[(middle + 1)..-1]) # Handle middle == ranges.length correctly.
42
44
 
43
45
  ary = [left, range, right].compact
44
46
 
45
47
  Node.new(left, range, right,
46
- ary.map(&:min).min, # Subtree's min.
47
- ary.map(&:max).max) # Subtree's max.
48
+ ary.map(&:min).min, # Subtree's min.
49
+ ary.map(&:max).max) # Subtree's max.
48
50
  end
49
51
 
50
52
  def search(range, limit: Float::INFINITY)
@@ -59,8 +61,7 @@ module HighLevelBrowse
59
61
  def self.search_helper(q, root, result, limit)
60
62
  return if root.nil?
61
63
  # Visit left child?
62
- if (l = root.left) and l.max and q.min and \
63
- not l.max < q.min # The interesting part.
64
+ if (l = root.left) && l.max && q.min && (l.max >= q.min) # The interesting part.
64
65
  search_helper(q, root.left, result, limit)
65
66
  end
66
67
 
@@ -78,8 +79,7 @@ module HighLevelBrowse
78
79
  result << root.range if RangeTree.ranges_intersect?(q, root.range)
79
80
 
80
81
  # Visit right child?
81
- if (r = root.right) and q.max and r.min and \
82
- not q.max < r.min # The interesting part.
82
+ if (r = root.right) && q.max && r.min && (q.max >= r.min) # The interesting part.
83
83
  search_helper(q, root.right, result, limit)
84
84
  end
85
85
  end
@@ -1,3 +1,3 @@
1
- module HighLevelBrowse
2
- VERSION = "1.0.0"
3
- end
1
+ module HighLevelBrowse
2
+ VERSION = "1.1.0"
3
+ end
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "high_level_browse/version"
2
- require 'high_level_browse/db'
3
- require 'uri'
4
- require 'open-uri'
4
+ require "high_level_browse/db"
5
+ require "uri"
6
+ require "open-uri"
5
7
 
6
8
  module HighLevelBrowse
7
-
8
- SOURCE_URL = ENV['HLB_XML_ENDPOINT'] || 'https://www.lib.umich.edu/browse/categories/xml.php'
9
+ SOURCE_URL = ENV["HLB_XML_ENDPOINT"] || "https://www.lib.umich.edu/browse/categories/xml.php"
9
10
 
10
11
  # Fetch a new version of the raw file and turn it into a db
11
12
  # @return [DB] The loaded database
@@ -15,27 +16,25 @@ module HighLevelBrowse
15
16
  uri.extend OpenURI::OpenRead
16
17
 
17
18
  xml = uri.read
18
- return DB.new_from_xml(xml)
19
+
20
+ DB.new_from_xml(xml)
19
21
  rescue => e
20
22
  raise "Could not fetch xml from '#{SOURCE_URL}': #{e}"
21
23
  end
22
24
 
23
-
24
25
  # Fetch and save to the specified directory
25
26
  # @param [String] dir The directory where the hlb.json.gz file will end up
26
27
  # @return [DB] The fetched and saved database
27
28
  def self.fetch_and_save(dir:)
28
- db = self.fetch
29
+ db = fetch
29
30
  db.save(dir: dir)
30
31
  db
31
32
  end
32
33
 
33
-
34
34
  # Load from disk
35
35
  # @param [String] dir The directory where the hlb.json.gz file is located
36
36
  # @return [DB] The loaded database
37
37
  def self.load(dir:)
38
38
  DB.load(dir: dir)
39
39
  end
40
-
41
40
  end
Binary file
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe HighLevelBrowse do
4
+
5
+ let(:hlb) { HighLevelBrowse.fetch }
6
+
7
+ it "has a version number" do
8
+ expect(HighLevelBrowse::VERSION).not_to be nil
9
+ end
10
+
11
+ it "runs basic sanity checks" do
12
+ expect(hlb['QA1']).to eq([["Science", "Mathematics"]])
13
+ expect(hlb['P11']).to eq [["Humanities", "Linguistics"]]
14
+ expect(hlb['AAA11']).to eq []
15
+ end
16
+
17
+ it "can do a basic save/load" do
18
+ dir = Dir.tmpdir
19
+ HighLevelBrowse.fetch_and_save(dir: dir)
20
+ loaded = HighLevelBrowse.load(dir: dir)
21
+ expect(loaded['QA1']).to eq [["Science", "Mathematics"]]
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ require "bundler/setup"
2
+ require "high_level_browse"
3
+
4
+ RSpec.configure do |config|
5
+ # Enable flags like --only-failures and --next-failure
6
+ config.example_status_persistence_file_path = ".rspec_status"
7
+
8
+ # Disable RSpec exposing methods globally on `Module` and `main`
9
+ config.disable_monkey_patching!
10
+
11
+ config.expect_with :rspec do |c|
12
+ c.syntax = :expect
13
+ end
14
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: high_level_browse
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bill Dueber
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-19 00:00:00.000000000 Z
11
+ date: 2022-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -53,7 +53,35 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: minitest
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: standard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
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: pry
57
85
  requirement: !ruby/object:Gem::Requirement
58
86
  requirements:
59
87
  - - ">="
@@ -76,7 +104,9 @@ executables:
76
104
  extensions: []
77
105
  extra_rdoc_files: []
78
106
  files:
107
+ - ".github/workflows/ruby.yml"
79
108
  - ".gitignore"
109
+ - ".rspec"
80
110
  - ".travis.yml"
81
111
  - CHANGELOG.md
82
112
  - Gemfile
@@ -92,8 +122,9 @@ files:
92
122
  - lib/high_level_browse/db.rb
93
123
  - lib/high_level_browse/range_tree.rb
94
124
  - lib/high_level_browse/version.rb
95
- - test/minitest_helper.rb
96
- - test/test_high_level_browse.rb
125
+ - spec/data/hlb.json.gz
126
+ - spec/high_level_browse_spec.rb
127
+ - spec/spec_helper.rb
97
128
  homepage: ''
98
129
  licenses:
99
130
  - MIT
@@ -118,5 +149,6 @@ signing_key:
118
149
  specification_version: 4
119
150
  summary: Map LC call numbers to academic categories.
120
151
  test_files:
121
- - test/minitest_helper.rb
122
- - test/test_high_level_browse.rb
152
+ - spec/data/hlb.json.gz
153
+ - spec/high_level_browse_spec.rb
154
+ - spec/spec_helper.rb
@@ -1,13 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
-
3
- # Both oga and minitest have stupid warnings that I don't want to
4
- # hear about
5
-
6
- verbose = $VERBOSE
7
- $VERBOSE = nil
8
- require 'minitest'
9
- require 'minitest/spec'
10
- require 'minitest/autorun'
11
- $VERBOSE = verbose
12
-
13
- require 'high_level_browse'
@@ -1,15 +0,0 @@
1
- require 'minitest_helper'
2
-
3
- require 'json'
4
- TESTDIR = File.expand_path(File.dirname(__FILE__))
5
-
6
- describe "loads" do
7
- it "loads" do
8
- assert true
9
- end
10
-
11
- it "has a version" do
12
- HighLevelBrowse::VERSION.wont_be_nil
13
- end
14
- end
15
-