marc_alephsequential 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/ChangeLog.md +4 -0
- data/Gemfile +4 -2
- data/README.md +1 -1
- data/Rakefile +0 -2
- data/lib/marc_alephsequential/asline.rb +53 -56
- data/lib/marc_alephsequential/asline_group.rb +25 -26
- data/lib/marc_alephsequential/asline_reader.rb +2 -2
- data/lib/marc_alephsequential/buffered_linereader.rb +33 -34
- data/lib/marc_alephsequential/error.rb +4 -4
- data/lib/marc_alephsequential/log.rb +6 -6
- data/lib/marc_alephsequential/reader.rb +17 -18
- data/lib/marc_alephsequential/version.rb +2 -1
- data/spec/asline_group_spec.rb +13 -12
- data/spec/asline_spec.rb +11 -11
- data/spec/helper.rb +2 -4
- data/spec/reader_spec.rb +9 -10
- data/spec/version_spec.rb +0 -1
- metadata +11 -12
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NmMwMWQzMTIzMmQ3ZmNlOTM5YjRiMGFmZTI2MTA3NmM0Njk0ZTJiYg==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9fa0b67408536b4221359c3a268ea99925ba55c9
|
4
|
+
data.tar.gz: 5ab21aa3f34c6b24af9fddc7e64c4eeab7f5ddac
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
OTM4ZDBhMTA3ZDZiYmY0YWU3M2I5NWM5MzBlYjhkY2QxNGZhNDdhMDAyM2Qx
|
11
|
-
MjQ4YWFiNTkxMjhmODk3Mzc0YjIzMGVlMzVmYzRlOTc0Y2Y3YmE=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
OWZmOGVkYWVkZTM4ZGQ1YmM1NGMzNzBkM2IwY2I4NmZmMmI1OTYzN2FhMTQw
|
14
|
-
NDcwMDQ0Zjk3MzdiZWQxN2M1ZmQzMGRhYWFkNTg5NGFiNTY4Yjk4N2JiMTFi
|
15
|
-
ZWEyZjJkMThkY2RlM2VjYmZhNTQ1NmYxYzM5NDhlN2QyOGY3MGE=
|
6
|
+
metadata.gz: 85513438e1ba85f181543bf83b67b9f34f7d09b06f262c6f890a7d4bce95014e00cfded966a1294d9a9de341883e1f55a41d881e5c7c2cd4ee7e7fbb35f6776a
|
7
|
+
data.tar.gz: 901c12d9c9830fccc112ebe89f9d77cc4708dad2f91dff6c685902c92921975a5c32eaa3cc4f4118ffd31a0de17c58f38ea22c4ce39cc44a41070d540f3668f1
|
data/ChangeLog.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -4,64 +4,64 @@ require_relative 'log'
|
|
4
4
|
|
5
5
|
module MARC
|
6
6
|
module AlephSequential
|
7
|
-
|
8
|
-
|
7
|
+
|
8
|
+
|
9
9
|
# A model of a line (field) in an alephsequential file.
|
10
10
|
class ASLine
|
11
|
-
|
11
|
+
|
12
12
|
include Log
|
13
13
|
|
14
14
|
# Characters in leader/control fields that need to be turned (back) into spaces
|
15
|
-
TURN_TO_SPACE
|
15
|
+
TURN_TO_SPACE = /\^/
|
16
16
|
|
17
|
-
# Pattern used to split data field values into subfield code/value pairs
|
17
|
+
# Pattern used to split data field values into subfield code/value pairs
|
18
18
|
SUBFIELD_SPLIT_PATTERN = /\$\$([a-zA-Z0-9])/
|
19
|
-
|
19
|
+
|
20
20
|
# How to know if we have a valid id? Must be 9 digits
|
21
|
-
VALID_ID
|
22
|
-
|
21
|
+
VALID_ID = /^\d{9}$/
|
22
|
+
|
23
23
|
# The passed in raw string, used for post-processing later on
|
24
24
|
attr_accessor :rawstr
|
25
|
-
|
25
|
+
|
26
26
|
# The line number in the file/stream, for error reporting
|
27
27
|
attr_accessor :line_number
|
28
|
-
|
28
|
+
|
29
29
|
# Either the value of a control/fiexed field, or a string representation of a datafield's subfield
|
30
30
|
attr_accessor :value
|
31
|
-
|
31
|
+
|
32
32
|
# The type of field (:leader, :control, :data, or :invalid_id)
|
33
33
|
attr_accessor :type
|
34
|
-
|
35
|
-
attr_accessor :id,
|
34
|
+
|
35
|
+
attr_accessor :id, :tag, :ind1, :ind2
|
36
36
|
|
37
37
|
# The MARC field's tag
|
38
38
|
attr_reader :tag
|
39
|
-
|
40
|
-
|
39
|
+
|
40
|
+
|
41
41
|
# Given a raw string and a line number, construct the appropriate ASLine.
|
42
|
-
#
|
43
|
-
# @param [String] rawstr The raw string from the file
|
42
|
+
#
|
43
|
+
# @param [String] rawstr The raw string from the file
|
44
44
|
# @param [Number] line_number The line number from the file/stream, for error reporting
|
45
|
-
|
45
|
+
|
46
46
|
def initialize(rawstr, line_number)
|
47
|
-
@rawstr
|
47
|
+
@rawstr = rawstr.chomp
|
48
48
|
@line_number = line_number
|
49
|
-
|
50
|
-
(self.id,self.tag,self.ind1,self.ind2,self.value) = *(parseline(@rawstr))
|
51
|
-
|
49
|
+
|
50
|
+
(self.id, self.tag, self.ind1, self.ind2, self.value) = *(parseline(@rawstr))
|
51
|
+
|
52
52
|
# clean up the leader or fixed fields
|
53
53
|
if [:leader, :control].include? self.type
|
54
54
|
self.value = cleanup_fixed(self.value)
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
end
|
58
|
-
|
59
|
-
# Does this line have a valid (-looking) id?
|
58
|
+
|
59
|
+
# Does this line have a valid (-looking) id?
|
60
60
|
def valid_id?
|
61
61
|
return VALID_ID.match(id) ? true : false
|
62
62
|
end
|
63
|
-
|
64
|
-
|
63
|
+
|
64
|
+
|
65
65
|
# Turn it into an actual MARC field (control or data)
|
66
66
|
# Throw an error if called on a leader (LDR) line
|
67
67
|
# @return [MARC::ControlField, MARC::DataField]
|
@@ -72,16 +72,16 @@ module MARC
|
|
72
72
|
when :data
|
73
73
|
self.to_data_field
|
74
74
|
else
|
75
|
-
raise MARC::AlephSequential::Error.new(id, line_number
|
75
|
+
raise MARC::AlephSequential::Error.new(id, line_number), "Tried to call #to_field on line type '#{self.type}'", nil
|
76
76
|
end
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
# Turn the current object into a control field, without doing any checks
|
80
80
|
# @return [MARC::ControlField]
|
81
81
|
def to_control_field
|
82
82
|
MARC::ControlField.new(tag, cleanup_fixed(self.value))
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
# Turn the current object into a datafield, without doing any checks
|
86
86
|
# @return [MARC::DataField]
|
87
87
|
def to_data_field
|
@@ -90,38 +90,38 @@ module MARC
|
|
90
90
|
self.value = '$$a' + self.value
|
91
91
|
end
|
92
92
|
|
93
|
-
subfields
|
94
|
-
f
|
93
|
+
subfields = parse_string_into_subfields(value)
|
94
|
+
f = MARC::DataField.new(tag, ind1, ind2)
|
95
95
|
f.subfields = subfields
|
96
96
|
return f
|
97
|
-
end
|
98
|
-
|
97
|
+
end
|
98
|
+
|
99
99
|
# Parse out a non-controlfield value string into a set of subfields
|
100
100
|
# @param [String] val the value string, of the form "$$athis is the a$$band the b"
|
101
101
|
# @return [Array<Subfield>] An array of MARC subfields
|
102
102
|
#
|
103
103
|
# If the first value in the array returned by the split isn't the empty string, then
|
104
|
-
# the string didn't start with '$$' and we should throw a warning
|
104
|
+
# the string didn't start with '$$' and we should throw a warning
|
105
105
|
# (and put the value into a subfield 'a' if we're running in flexible mode)
|
106
|
-
|
106
|
+
|
107
107
|
def parse_string_into_subfields(val)
|
108
|
-
sfpairs
|
108
|
+
sfpairs = val.split(SUBFIELD_SPLIT_PATTERN)
|
109
109
|
initial_null_string = sfpairs.shift
|
110
110
|
unless initial_null_string == ''
|
111
111
|
# do something about the error
|
112
112
|
end
|
113
|
-
|
114
|
-
sfpairs.each_slice(2).map {|code, val| MARC::Subfield.new(code, val) }
|
115
|
-
|
113
|
+
|
114
|
+
sfpairs.each_slice(2).map { |code, val| MARC::Subfield.new(code, val) }
|
115
|
+
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
# Clean up fixed fields/leader, turning Ex Libris characters back into normal characters
|
119
119
|
# @param [String] val The string to clean
|
120
120
|
# @return [String] The cleaned string
|
121
121
|
def cleanup_fixed(val)
|
122
122
|
return val.gsub(TURN_TO_SPACE, ' ')
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
# Set the tag. As a side effect, set the type when we set the tag
|
126
126
|
# type will end up as :leader, :control, :data, or :invalid_id
|
127
127
|
def tag=(t)
|
@@ -136,26 +136,23 @@ module MARC
|
|
136
136
|
self.type = :invalid_id
|
137
137
|
end
|
138
138
|
end
|
139
|
-
|
140
|
-
|
139
|
+
|
140
|
+
|
141
141
|
# Get a line and parse it out into its componant parts
|
142
142
|
# @param [String] line the line to parse
|
143
143
|
# @return [Array] An array of the form [id, tag, ind1, ind2, value]
|
144
|
-
|
144
|
+
|
145
145
|
def parseline(line)
|
146
|
-
id
|
147
|
-
tag
|
148
|
-
ind1
|
149
|
-
ind2
|
146
|
+
id = line[0, 9]
|
147
|
+
tag = line[10, 3]
|
148
|
+
ind1 = line[13, 1]
|
149
|
+
ind2 = line[14, 1]
|
150
150
|
value = line[18..-1]
|
151
|
-
return [id,tag,ind1,ind2,value]
|
151
|
+
return [id, tag, ind1, ind2, value]
|
152
152
|
end
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
153
|
+
|
154
|
+
|
157
155
|
end # ASLine
|
158
156
|
end
|
159
157
|
end
|
160
|
-
|
161
|
-
|
158
|
+
|
@@ -5,48 +5,47 @@ require_relative 'log'
|
|
5
5
|
|
6
6
|
module MARC
|
7
7
|
module AlephSequential
|
8
|
-
|
8
|
+
|
9
9
|
# A group of ASLine objects with logic to correctly turn them into a MARC::Record object
|
10
10
|
# @see ASLine
|
11
|
-
|
11
|
+
|
12
12
|
class ASLineGroup
|
13
|
-
|
13
|
+
|
14
14
|
include Log
|
15
|
-
|
15
|
+
|
16
16
|
# @!attribute aslines
|
17
17
|
# @return [Array<MARC::Field>] Internal list of MARC field object
|
18
18
|
attr_accessor :aslines
|
19
|
-
|
19
|
+
|
20
20
|
# @!attribute [r] leader
|
21
21
|
# @return [String] The leader string, pulled from whatever was passed in with a LDR tag
|
22
|
-
attr_reader
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
attr_reader :leader
|
23
|
+
|
24
|
+
|
26
25
|
def initialize
|
27
26
|
@aslines = []
|
28
|
-
@leader
|
27
|
+
@leader = nil
|
29
28
|
end
|
30
|
-
|
29
|
+
|
31
30
|
# Number of aslines already added
|
32
31
|
# @return Integer
|
33
32
|
def size
|
34
33
|
aslines.size
|
35
34
|
end
|
36
|
-
|
35
|
+
|
37
36
|
# Is this group empty?
|
38
37
|
def empty?
|
39
38
|
aslines.empty?
|
40
39
|
end
|
41
|
-
|
42
|
-
|
40
|
+
|
41
|
+
|
43
42
|
# Add an ASLine object, turning it into the appropriate type of field as we go
|
44
43
|
# An ASLine object with type :invalid_id will be treated as a string and appended to
|
45
44
|
# the previous field (to deal with not-uncommon spurious newlines in data fields)
|
46
45
|
# @return [Undefined] side effect only
|
47
46
|
# @raise MARC::AlephSequential::Error when there's an invalid ID _and_ there's no previous
|
48
47
|
# field to concatentate it to.
|
49
|
-
|
48
|
+
|
50
49
|
def add(asline)
|
51
50
|
case asline.type
|
52
51
|
when :leader
|
@@ -57,23 +56,23 @@ module MARC
|
|
57
56
|
when :invalid_id
|
58
57
|
lastfield = @aslines.pop
|
59
58
|
unless lastfield
|
60
|
-
raise MARC::AlephSequential::Error.new('unknown', asline.line_number),
|
59
|
+
raise MARC::AlephSequential::Error.new('unknown', asline.line_number),
|
61
60
|
"#{asline.line_number} has invalid id and no preivous line to concat it to (file starts bad?)"
|
62
|
-
|
61
|
+
nil
|
63
62
|
end
|
64
63
|
log.info "#{asline.line_number} #{lastfield.id} / #{lastfield.tag} Concatenating line #{asline.line_number} to previous line"
|
65
|
-
@aslines.push ASLine.new(lastfield.rawstr +
|
64
|
+
@aslines.push ASLine.new(lastfield.rawstr + asline.rawstr, lastfield.line_number)
|
66
65
|
else
|
67
66
|
@aslines.push asline
|
68
67
|
end
|
69
68
|
end
|
70
|
-
|
71
|
-
|
69
|
+
|
70
|
+
|
72
71
|
# Add an asline as a raw string
|
73
72
|
def add_string(asline_string, line_number)
|
74
73
|
self.add(ASLine.new(asline_string, line_number))
|
75
74
|
end
|
76
|
-
|
75
|
+
|
77
76
|
# Turn this object into a MARC::Record
|
78
77
|
# @return [MARC::Record]
|
79
78
|
# @raise MARC::AlephSequential::Error if this object is empty
|
@@ -82,20 +81,20 @@ module MARC
|
|
82
81
|
if empty?
|
83
82
|
raise MARC::AlephSequential::Error.new('unknown', 'unknown'), "Can't turn an empty group into a record", nil
|
84
83
|
end
|
85
|
-
|
84
|
+
|
86
85
|
unless leader
|
87
86
|
raise MARC::AlephSequential::Error.new(@aslines[0].id, @aslines[0].line_number),
|
88
87
|
"Record #{@aslines[0].id} (near line #{ @aslines[0].line_number}) has no leader; can't turn into a record",
|
89
88
|
nil
|
90
89
|
end
|
91
|
-
r
|
90
|
+
r = MARC::Record.new
|
92
91
|
r.leader = leader
|
93
|
-
aslines.map {|f| r << f.to_field}
|
92
|
+
aslines.map { |f| r << f.to_field }
|
94
93
|
return r
|
95
94
|
end
|
96
|
-
|
95
|
+
|
97
96
|
alias_method :to_record, :as_record
|
98
97
|
end
|
99
98
|
end
|
100
99
|
end
|
101
|
-
|
100
|
+
|
@@ -3,52 +3,52 @@ require 'zlib'
|
|
3
3
|
module MARC
|
4
4
|
module AlephSequential
|
5
5
|
|
6
|
-
# AlephSequential is a line-oriented format, with the first field of each line
|
6
|
+
# AlephSequential is a line-oriented format, with the first field of each line
|
7
7
|
# indicating the record number. Rather than try to screw around with keeping track of
|
8
8
|
# the last line read, checking to see if we have one, blah blah blah, I'm going to use
|
9
|
-
# a buffered line reader class so I can #peek at the next line to know if its id
|
10
|
-
# is different than the current record.
|
11
|
-
|
9
|
+
# a buffered line reader class so I can #peek at the next line to know if its id
|
10
|
+
# is different than the current record.
|
11
|
+
|
12
12
|
class BufferedLineReader
|
13
|
-
|
13
|
+
|
14
14
|
include Enumerable
|
15
|
-
|
15
|
+
|
16
16
|
attr_accessor :buffer_size
|
17
17
|
attr_reader :underlying_line_number
|
18
|
-
|
18
|
+
|
19
19
|
def initialize(filename_or_io)
|
20
|
-
|
20
|
+
|
21
21
|
@passed_in = filename_or_io
|
22
|
-
|
22
|
+
|
23
23
|
@underlying_line_number = 0
|
24
|
-
@buffer_size
|
25
|
-
@buffer
|
26
|
-
|
24
|
+
@buffer_size = 10
|
25
|
+
@buffer = []
|
26
|
+
|
27
27
|
if filename_or_io.is_a? String
|
28
28
|
@handle = File.open(filename_or_io, 'r:utf-8')
|
29
29
|
if filename_or_io =~ /\.gz$/
|
30
30
|
@handle = Zlib::GzipReader.new(@handle)
|
31
31
|
end
|
32
|
-
elsif filename_or_io.respond_to?("read"
|
32
|
+
elsif filename_or_io.respond_to?("read")
|
33
33
|
@handle = filename_or_io
|
34
34
|
else
|
35
35
|
raise ArgumentError.new("BufferedLineReader needs an IO object or filename, got #{filename_or_io} (#{filename_or_io.inspect})")
|
36
36
|
end
|
37
|
-
|
38
|
-
@iter
|
37
|
+
|
38
|
+
@iter = @handle.enum_for(:each_line)
|
39
39
|
@finished = false
|
40
40
|
# Fill up the buffer
|
41
41
|
self.fillbuffer
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def has_next?
|
45
45
|
return !(@finished && @buffer.size == 0)
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def fillbuffer(buffer_size = @buffer_size)
|
49
49
|
begin
|
50
50
|
buffer_size.times do
|
51
|
-
raw
|
51
|
+
raw = @iter.next
|
52
52
|
@underlying_line_number += 1
|
53
53
|
@buffer.push process_raw(raw, @underlying_line_number)
|
54
54
|
end
|
@@ -56,25 +56,25 @@ module MARC
|
|
56
56
|
@finished = true
|
57
57
|
end
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
# Empty version here; can override for processing lines on the fly
|
61
61
|
def process_raw(raw, line_number)
|
62
62
|
raw
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
def next
|
66
66
|
raise StopIteration, "End of #{@passed_in}", nil if @buffer.size == 0
|
67
67
|
rv = @buffer.shift
|
68
68
|
fillbuffer if @buffer.size == 0
|
69
69
|
rv
|
70
70
|
end
|
71
|
-
|
72
|
-
|
71
|
+
|
72
|
+
|
73
73
|
def peek
|
74
74
|
fillbuffer unless @buffer.size > 0
|
75
75
|
@buffer[0]
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
def each
|
79
79
|
begin
|
80
80
|
while true
|
@@ -83,18 +83,17 @@ module MARC
|
|
83
83
|
rescue StopIteration
|
84
84
|
end
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
alias_method :each_line, :each
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module MARC
|
2
2
|
module AlephSequential
|
3
|
-
|
3
|
+
|
4
4
|
class Error < RuntimeError
|
5
5
|
attr_accessor :record_id, :line_number
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(record_id, line_number)
|
8
|
-
@record_id
|
8
|
+
@record_id = record_id
|
9
9
|
@line_number = line_number
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
13
|
-
end
|
13
|
+
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
module MARC
|
2
2
|
module AlephSequential
|
3
|
-
|
3
|
+
|
4
4
|
module Log
|
5
|
-
|
5
|
+
|
6
6
|
def self.log
|
7
7
|
@log
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def self.log=(log)
|
11
11
|
@log = log
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def log
|
15
|
-
Log.log ||= Yell.new STDERR, :level => [
|
15
|
+
Log.log ||= Yell.new STDERR, :level => [:warn, :error], :name => 'MAS'
|
16
16
|
Log.log
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
20
|
-
end
|
20
|
+
end
|
@@ -6,32 +6,32 @@ require 'marc_alephsequential/log'
|
|
6
6
|
|
7
7
|
module MARC
|
8
8
|
module AlephSequential
|
9
|
-
|
9
|
+
|
10
10
|
class Reader
|
11
11
|
|
12
12
|
include Enumerable
|
13
13
|
include Log
|
14
|
-
|
14
|
+
|
15
15
|
attr_reader :lines
|
16
16
|
attr_accessor :current_id
|
17
|
-
|
17
|
+
|
18
18
|
def initialize(filename_or_io, opts={})
|
19
19
|
@areader = ASLineReader.new(filename_or_io)
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def each
|
23
|
-
|
23
|
+
|
24
24
|
unless block_given?
|
25
25
|
return enum_for(:each)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
agroup = ASLineGroup.new
|
29
|
-
|
29
|
+
|
30
30
|
while @areader.has_next?
|
31
31
|
nextid = @areader.peek.id
|
32
|
-
if nextid != @current_id && @areader.peek.valid_id?
|
32
|
+
if nextid != @current_id && @areader.peek.valid_id?
|
33
33
|
yield agroup.to_record unless agroup.empty?
|
34
|
-
agroup
|
34
|
+
agroup = ASLineGroup.new
|
35
35
|
@current_id = nextid
|
36
36
|
else
|
37
37
|
agroup.add @areader.next
|
@@ -43,12 +43,11 @@ module MARC
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
|
data/spec/asline_group_spec.rb
CHANGED
@@ -8,16 +8,17 @@ describe "ASLineGroup" do
|
|
8
8
|
@single_lines.each_with_index {|l,i| @full.add_string(l,i ) }
|
9
9
|
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
|
+
|
12
13
|
describe "Create Group" do
|
13
14
|
before do
|
14
15
|
@ag = MARC::AlephSequential::ASLineGroup.new
|
15
16
|
end
|
16
|
-
|
17
|
+
|
17
18
|
it "should start empty" do
|
18
19
|
@ag.must_be_empty
|
19
20
|
end
|
20
|
-
|
21
|
+
|
21
22
|
it "should read in a valid record" do
|
22
23
|
@ag = MARC::AlephSequential::ASLineGroup.new
|
23
24
|
File.open('spec/data/single.seq').each_with_index {|l,i| @ag.add_string(l,i ) }
|
@@ -27,7 +28,7 @@ describe "ASLineGroup" do
|
|
27
28
|
@ag.aslines[1].tag.must_equal '003'
|
28
29
|
@ag.aslines[1].type.must_equal :control
|
29
30
|
end
|
30
|
-
|
31
|
+
|
31
32
|
it "should deal with embedded newlines" do
|
32
33
|
tinyrec = [
|
33
34
|
"000000794 LDR L ^^^^^nam^a22003011^^4500",
|
@@ -37,23 +38,23 @@ describe "ASLineGroup" do
|
|
37
38
|
"Curtis,$$d1859-1937.",
|
38
39
|
"000000794 24514 L $$aThe descent of manuscripts"
|
39
40
|
]
|
40
|
-
|
41
|
+
|
41
42
|
tinyrec.each_with_index {|l,i| @ag.add_string(l,i) }
|
42
43
|
field = @ag.aslines[2].to_field
|
43
44
|
field.tag.must_equal '100'
|
44
45
|
field['a'].must_equal 'Clark, Albert Curtis,'
|
45
46
|
end
|
46
|
-
|
47
|
+
|
47
48
|
it "should produce a good record" do
|
48
49
|
rec = @full.to_record
|
49
50
|
rec['001'].value.must_equal '000000794'
|
50
51
|
rec['998'].value.must_equal '9665'
|
51
52
|
end
|
52
|
-
|
53
|
-
|
54
|
-
|
53
|
+
|
54
|
+
|
55
|
+
|
55
56
|
end
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
|
58
|
+
|
59
|
+
|
59
60
|
end
|
data/spec/asline_spec.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'helper'
|
2
2
|
require 'marc_alephsequential'
|
3
3
|
|
4
|
+
|
4
5
|
describe 'ASLine' do
|
5
6
|
before do
|
6
7
|
@leader = '000000794 LDR L ^^^^^nam^a22003011^^4500'
|
@@ -9,27 +10,27 @@ describe 'ASLine' do
|
|
9
10
|
@d1 = '000000794 1001 L $$aClark, Albert Curtis,$$d1859-1937.'
|
10
11
|
@d2 = '000000794 60000 L $$aPlato.$$tCritias$$xManuscripts.'
|
11
12
|
end
|
12
|
-
|
13
|
-
|
13
|
+
|
14
|
+
|
14
15
|
it "correctly parses a leader" do
|
15
16
|
aline = MARC::AlephSequential::ASLine.new(@leader, 1)
|
16
17
|
aline.type.must_equal :leader
|
17
18
|
aline.value.must_equal ' nam a22003011 4500'
|
18
19
|
end
|
19
|
-
|
20
|
+
|
20
21
|
it "parses control fields" do
|
21
22
|
aline = MARC::AlephSequential::ASLine.new(@c1, 1)
|
22
23
|
aline.tag.must_equal '008'
|
23
24
|
aline.value.must_equal '880715r19701918enk b |00100 eng '
|
24
25
|
end
|
25
|
-
|
26
|
-
it "parses datafield basics" do
|
26
|
+
|
27
|
+
it "parses datafield basics" do
|
27
28
|
aline = MARC::AlephSequential::ASLine.new(@d1, 1)
|
28
29
|
aline.tag.must_equal '100'
|
29
30
|
aline.ind1.must_equal '1'
|
30
31
|
aline.ind2.must_equal ' '
|
31
32
|
end
|
32
|
-
|
33
|
+
|
33
34
|
it "parses subfields" do
|
34
35
|
aline = MARC::AlephSequential::ASLine.new(@d1, 1)
|
35
36
|
subfields = aline.parse_string_into_subfields(aline.value)
|
@@ -37,10 +38,9 @@ describe 'ASLine' do
|
|
37
38
|
subfields[1].code.must_equal 'd'
|
38
39
|
subfields[0].value.must_equal 'Clark, Albert Curtis,'
|
39
40
|
subfields[1].value.must_equal '1859-1937.'
|
40
|
-
|
41
|
+
|
41
42
|
end
|
42
|
-
|
43
|
-
|
44
|
-
|
43
|
+
|
44
|
+
|
45
|
+
|
45
46
|
end
|
46
|
-
|
data/spec/helper.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
|
3
1
|
begin
|
4
2
|
require 'bundler'
|
5
3
|
rescue LoadError => e
|
@@ -18,5 +16,5 @@ end
|
|
18
16
|
|
19
17
|
require "minitest/autorun"
|
20
18
|
# require 'minitest/reporters'
|
21
|
-
# MiniTest::Reporters.use!
|
22
|
-
require 'minitest/hell' # parallelize testing
|
19
|
+
# MiniTest::Reporters.use!
|
20
|
+
require 'minitest/hell' # parallelize testing
|
data/spec/reader_spec.rb
CHANGED
@@ -8,29 +8,29 @@ describe 'Reader' do
|
|
8
8
|
@newline = 'spec/data/newline.seq'
|
9
9
|
@noleader = 'spec/data/noleader.seq'
|
10
10
|
@nosubfieldindicator = 'spec/data/no_initial_subfield.seq'
|
11
|
-
|
11
|
+
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
describe "empty reader" do
|
15
15
|
it "doesn't blow up on an empty file" do
|
16
16
|
iter = MARC::AlephSequential::Reader.new('/dev/null').each
|
17
17
|
lambda{iter.next}.must_raise StopIteration
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
it "reads a single record from a single-record file" do
|
22
22
|
iter = MARC::AlephSequential::Reader.new(@single).each
|
23
23
|
r = iter.next
|
24
24
|
r['998'].value.must_equal '9665'
|
25
25
|
r['100']['a'].must_equal 'Clark, Albert Curtis,'
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
it "reads a batch of records" do
|
29
29
|
count = 0
|
30
30
|
MARC::AlephSequential::Reader.new(@batch).each_with_index{|r, i| count = i + 1}
|
31
31
|
count.must_equal 31
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
it "yells when there's no leader" do
|
35
35
|
error = nil
|
36
36
|
begin
|
@@ -41,13 +41,13 @@ describe 'Reader' do
|
|
41
41
|
error.wont_be_nil
|
42
42
|
error.message.must_match /leader/
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
it "deals ok with embedded newline" do
|
46
46
|
r = MARC::AlephSequential::Reader.new(@newline).first
|
47
47
|
r['600']['a'].must_equal 'Cicero, Marcus Tullius'
|
48
48
|
r['600']['x'].must_equal 'Manuscripts.'
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
it "works with lack of beginning '$$'" do
|
52
52
|
r = nil # capture_io creates a lexical closure, so we need to define it out here
|
53
53
|
out,err = capture_io do
|
@@ -56,7 +56,6 @@ describe 'Reader' do
|
|
56
56
|
err.must_match /Variable field 245 doesn\'t start with \'\$\$/m
|
57
57
|
r['245']['a'].must_equal 'The descent of manuscripts.'
|
58
58
|
end
|
59
|
-
|
60
|
-
|
59
|
+
|
60
|
+
|
61
61
|
end
|
62
|
-
|
data/spec/version_spec.rb
CHANGED
metadata
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: marc_alephsequential
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bill Dueber
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-10-
|
11
|
+
date: 2013-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: A ruby-marc reader for Aleph sequential files, a MARC serialization supported
|
14
|
-
by Ex Libris' Aleph
|
13
|
+
description: A ruby-marc reader for Aleph sequential files, a MARC serialization supported by Ex Libris' Aleph
|
15
14
|
email: bill@dueber.com
|
16
15
|
executables: []
|
17
16
|
extensions: []
|
@@ -50,24 +49,24 @@ homepage: https://github.com/billdueber/marc_alephsequential#readme
|
|
50
49
|
licenses:
|
51
50
|
- MIT
|
52
51
|
metadata: {}
|
53
|
-
post_install_message:
|
52
|
+
post_install_message:
|
54
53
|
rdoc_options: []
|
55
54
|
require_paths:
|
56
55
|
- lib
|
57
56
|
required_ruby_version: !ruby/object:Gem::Requirement
|
58
57
|
requirements:
|
59
|
-
- -
|
58
|
+
- - '>='
|
60
59
|
- !ruby/object:Gem::Version
|
61
60
|
version: '0'
|
62
61
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
62
|
requirements:
|
64
|
-
- -
|
63
|
+
- - '>='
|
65
64
|
- !ruby/object:Gem::Version
|
66
65
|
version: '0'
|
67
66
|
requirements: []
|
68
|
-
rubyforge_project:
|
69
|
-
rubygems_version: 2.1.
|
70
|
-
signing_key:
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 2.1.9
|
69
|
+
signing_key:
|
71
70
|
specification_version: 4
|
72
71
|
summary: ruby-marc reader for Aleph sequential files
|
73
72
|
test_files:
|
@@ -81,4 +80,4 @@ test_files:
|
|
81
80
|
- spec/helper.rb
|
82
81
|
- spec/reader_spec.rb
|
83
82
|
- spec/version_spec.rb
|
84
|
-
has_rdoc:
|
83
|
+
has_rdoc:
|