marc 0.0.2

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.
@@ -0,0 +1,36 @@
1
+ module MARC
2
+
3
+ # A class for representing fields with a tag less than 010.
4
+ # Ordinary MARC::Field objects are for fields with tags >= 010
5
+ # which have indicators and subfields.
6
+
7
+ class Control
8
+
9
+ # the tag value (007, 008, etc)
10
+ attr_accessor :tag
11
+
12
+ # the value of the control field
13
+ attr_accessor :value
14
+
15
+ # The constructor which must be passed a tag value and
16
+ # an optional value for the field.
17
+
18
+ def initialize(tag,value='')
19
+ @tag = tag
20
+ @value = value
21
+ if tag.to_i > 9
22
+ raise MARC::Exception.new(), "tag must be greater than 009"
23
+ end
24
+ end
25
+
26
+ def to_s
27
+ return "#{tag} #{value}"
28
+ end
29
+
30
+ def =~(regex)
31
+ return self.to_s =~ regex
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,9 @@
1
+ module MARC
2
+
3
+ # basic exception class for exceptions that
4
+ # can occur during MARC processing.
5
+
6
+ class Exception < RuntimeError
7
+ end
8
+
9
+ end
data/lib/marc/field.rb ADDED
@@ -0,0 +1,141 @@
1
+ require 'marc/subfield'
2
+ require 'marc/record'
3
+
4
+ module MARC
5
+
6
+ # MARC records are made up of fields, each of which has a tag,
7
+ # indicators and subfields. If the tag is between 000-009 it is
8
+ # known as a control field, and actually does not have any
9
+ # indicators.
10
+
11
+ class Field
12
+ include Enumerable
13
+
14
+ # The tag for the field
15
+ attr_accessor :tag
16
+
17
+ # The first indicator
18
+ attr_accessor :indicator1
19
+
20
+ # The second indicator
21
+ attr_accessor :indicator2
22
+
23
+ # A list of MARC::Subfield objects
24
+ attr_accessor :subfields
25
+
26
+
27
+ # Create a new field with tag, indicators and subfields.
28
+ # Subfields are passed in as comma separated list of
29
+ # MARC::Subfield objects,
30
+ #
31
+ # field = MARC::Field.new('245','0','0',
32
+ # MARC::Subfield.new('a', 'Consilience :'),
33
+ # MARC::Subfield.new('b', 'the unity of knowledge ',
34
+ # MARC::Subfield.new('c', 'by Edward O. Wilson.'))
35
+ #
36
+ # or using a shorthand:
37
+ #
38
+ # field = MARC::Field.new('245','0','0',
39
+ # ['a', 'Consilience :'],['b','the unity of knowledge ',
40
+ # ['c', 'by Edward O. Wilson.'] )
41
+
42
+ def initialize(tag, i1=nil, i2=nil, *subfields)
43
+ @tag = tag
44
+ @indicator1 = i1
45
+ @indicator2 = i2
46
+ @subfields = []
47
+
48
+ # must use MARC::ControlField for tags < 010
49
+ if @tag.to_i < 10
50
+ raise MARC::Exception.new(),
51
+ "MARC::Field objects can't have tags < 010"
52
+ end
53
+
54
+ # allows MARC::Subfield objects to be passed directly
55
+ # or a shorthand of ['a','Foo'], ['b','Bar']
56
+ subfields.each do |subfield|
57
+ case subfield
58
+ when MARC::Subfield
59
+ @subfields.push(subfield)
60
+ when Array
61
+ if subfield.length > 2
62
+ raise MARC::Exception.new(),
63
+ "arrays must only have 2 elements"
64
+ end
65
+ @subfields.push(
66
+ MARC::Subfield.new(subfield[0],subfield[1]))
67
+ else
68
+ raise MARC::Exception.new(),
69
+ "invalid subfield type #{subfield.class}"
70
+ end
71
+ end
72
+ end
73
+
74
+
75
+ # Returns a string representation of the field such as:
76
+ # 245 00 $aConsilience :$bthe unity of knowledge $cby Edward O. Wilson.
77
+
78
+ def to_s
79
+ str = "#{tag} "
80
+ str += "#{indicator1}#{indicator2} "
81
+ @subfields.each { |subfield| str += subfield.to_s }
82
+ return str
83
+ end
84
+
85
+
86
+ # Add a subfield (MARC::Subfield) to the field
87
+ # field.append(MARC::Subfield('a','Dave Thomas'))
88
+
89
+ def append(subfield)
90
+ @subfields.push(subfield)
91
+ end
92
+
93
+
94
+ # You can iterate through the subfields in a Field:
95
+ # field.each {|s| print s}
96
+
97
+ def each
98
+ for subfield in subfields
99
+ yield subfield
100
+ end
101
+ end
102
+
103
+
104
+ # You can lookup subfields with this shorthand. Note it
105
+ # will return a string and not a MARC::Subfield object.
106
+ # subfield = field['a']
107
+
108
+ def [](code)
109
+ subfield = self.find {|s| s.code == code}
110
+ return subfield.value if subfield
111
+ return
112
+ end
113
+
114
+
115
+ # Two fields are equal if their tag, indicators and
116
+ # subfields are all equal.
117
+
118
+ def ==(other)
119
+ if @tag != other.tag
120
+ return false
121
+ elsif @indicator1 != other.indicator1
122
+ return false
123
+ elsif @indicator2 != other.indicator2
124
+ return false
125
+ elsif @subfields != other.subfields
126
+ return false
127
+ end
128
+ return true
129
+ end
130
+
131
+
132
+ # To support regex matching with fields
133
+ #
134
+ # if field =~ /Huckleberry/ ...
135
+
136
+ def =~(regex)
137
+ return self.to_s =~ regex
138
+ end
139
+
140
+ end
141
+ end
@@ -0,0 +1,132 @@
1
+ module MARC
2
+
3
+ # Provides methods for serializing and deserializing MARC::Record
4
+ # objects as MARC21 in transmission format.
5
+
6
+ class MARC21
7
+
8
+ LEADER_LENGTH = 24
9
+ DIRECTORY_ENTRY_LENGTH = 12
10
+ SUBFIELD_INDICATOR = 0x1F.chr
11
+ END_OF_FIELD = 0x1E.chr
12
+ END_OF_RECORD = 0x1D.chr
13
+
14
+
15
+ # Returns the MARC21 serialization for a MARC::Record
16
+
17
+ def encode(record)
18
+ directory = ''
19
+ fields = ''
20
+ offset = 0
21
+ for field in record.fields
22
+
23
+ # encode the field
24
+ field_data = ''
25
+ if field.class == MARC::Field
26
+ field_data = field.indicator1 + field.indicator2
27
+ for s in field.subfields
28
+ field_data += SUBFIELD_INDICATOR + s.code + s.value
29
+ end
30
+ elsif field.class == MARC::Control
31
+ field_data = field.value
32
+ end
33
+ field_data += END_OF_FIELD
34
+
35
+ # calculate directory entry for the field
36
+ field_length = field_data.length()
37
+ directory += sprintf("%03s%04i%05i", field.tag, field_length,
38
+ offset)
39
+
40
+ # add field to data for other fields
41
+ fields += field_data
42
+
43
+ # update offset for next field
44
+ offset += field_length
45
+ end
46
+
47
+ # determine the base (leader + directory)
48
+ base = record.leader + directory + END_OF_FIELD
49
+
50
+ # determine complete record
51
+ marc = base + fields + END_OF_RECORD
52
+
53
+ # update leader with the byte offest to the end of the directory
54
+ marc[12..16] = sprintf("%05i", base.length())
55
+
56
+ # update the record length
57
+ marc[0..4] = sprintf("%05i", marc.length())
58
+
59
+ # store updated leader in the record that was passed in
60
+ record.leader = marc[0..LEADER_LENGTH]
61
+
62
+ # return encoded marc
63
+ return marc
64
+ end
65
+
66
+
67
+ # Deserializes MARC21 as a MARC::Record object
68
+
69
+ def decode(marc)
70
+ record = Record.new()
71
+ record.leader = marc[0..LEADER_LENGTH]
72
+
73
+ # where the field data starts
74
+ base_address = record.leader[12..16].to_i
75
+
76
+ # get the byte offsets from the record directory
77
+ directory = marc[LEADER_LENGTH..base_address-1]
78
+
79
+ # the number of fields in the record corresponds to
80
+ # how many directory entries there are
81
+ num_fields = directory.length / DIRECTORY_ENTRY_LENGTH
82
+
83
+ 0.upto(num_fields-1) do |field_num|
84
+
85
+ # pull the directory entry for a field out
86
+ entry_start = field_num * DIRECTORY_ENTRY_LENGTH
87
+ entry_end = entry_start + DIRECTORY_ENTRY_LENGTH
88
+ entry = directory[entry_start..entry_end]
89
+
90
+ # extract the tag, length and offset for pulling the
91
+ # field out of the field portion
92
+ tag = entry[0..2]
93
+ length = entry[3..6].to_i
94
+ offset = entry[7..11].to_i
95
+ field_start = base_address + offset
96
+ field_end = field_start + length - 1
97
+ field_data = marc[field_start..field_end]
98
+
99
+ # remove end of field
100
+ field_data.delete!(END_OF_FIELD)
101
+
102
+ # add a control field or variable field
103
+ if tag < '010'
104
+ record.append(MARC::Control.new(tag,field_data))
105
+ else
106
+ field = MARC::Field.new(tag)
107
+
108
+ # get all subfields
109
+ subfields = field_data.split(SUBFIELD_INDICATOR)
110
+
111
+ # get indicators
112
+ indicators = subfields.shift()
113
+ field.indicator1 = indicators[0,1]
114
+ field.indicator2 = indicators[1,1]
115
+
116
+ # add each subfield to the field
117
+ subfields.each() do |data|
118
+ subfield = MARC::Subfield.new(data[0,1],data[1..-1])
119
+ field.append(subfield)
120
+ end
121
+
122
+ # add the field to the record
123
+ record.append(field)
124
+ end
125
+ end
126
+
127
+ return record
128
+ end
129
+
130
+ end
131
+
132
+ end
@@ -0,0 +1,51 @@
1
+ module MARC
2
+
3
+ class Reader
4
+ include Enumerable
5
+
6
+ # The constructor which you may pass either a path
7
+ #
8
+ # reader = MARC::Reader.new('marc.dat')
9
+ #
10
+ # or, if it's more convenient a File object:
11
+ #
12
+ # fh = File.new('marc.dat')
13
+ # reader = MARC::Reader.new(fh)
14
+ #
15
+ # or really any object that responds to read(n).
16
+
17
+ def initialize(file)
18
+ if file.class == String:
19
+ @handle = File.new(file)
20
+ elsif file.respond_to?("read", 5)
21
+ @handle = file
22
+ else
23
+ throw "must pass in path or file"
24
+ end
25
+ end
26
+
27
+ # to support iteration:
28
+ # for record in reader
29
+ # print record
30
+ # end
31
+ #
32
+ # and even searching:
33
+ # record.find { |f| f['245'] =~ /Huckleberry/ }
34
+
35
+ def each
36
+ # while there is data left in the file
37
+ while length = @handle.read(5)
38
+
39
+ # get the raw MARC21 for a record back from the file
40
+ # using the record length
41
+ raw = length + @handle.read(length.to_i-5)
42
+
43
+ # create a record from the data and return it
44
+ record = MARC::Record.new_from_marc(raw)
45
+ yield record
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,117 @@
1
+ module MARC
2
+
3
+ # A class that represents an individual MARC record. Every record
4
+ # is made up of a collection of MARC::Field objects.
5
+
6
+ class Record
7
+ include Enumerable
8
+
9
+ # the record fields
10
+ attr_accessor :fields,
11
+
12
+ # the record leader
13
+ :leader
14
+
15
+ def initialize
16
+ @fields = []
17
+ # leader is 24 bytes
18
+ @leader = ' ' * 24
19
+ # leader defaults:
20
+ # http://www.loc.gov/marc/bibliographic/ecbdldrd.html
21
+ @leader[10..11] = '22'
22
+ @leader[20..23] = '4500';
23
+ end
24
+
25
+ # add a field to the record
26
+ # record.append(MARC::Field.new( '100', '2', '0', ['a', 'Fred']))
27
+
28
+ def append(field)
29
+ @fields.push(field)
30
+ end
31
+
32
+ # each() is here to support iterating and searching since MARC::Record
33
+ # mixes in Enumberable
34
+ #
35
+ # iterating through the fields in a record:
36
+ # record.each { |f| print f }
37
+ #
38
+ # getting the 245
39
+ # title = record.find {|f| f.tag == '245'}
40
+ #
41
+ # getting all subjects
42
+ # subjects = record.find_all {|f| ('600'..'699' === f.tag)}
43
+
44
+ def each
45
+ for field in @fields
46
+ yield field
47
+ end
48
+ end
49
+
50
+ # You can lookup fields using this shorthand:
51
+ # title = record['245']
52
+
53
+ def [](tag)
54
+ return self.find {|f| f.tag == tag}
55
+ end
56
+
57
+ # Factory method for creating a MARC::Record from MARC21 in
58
+ # transmission format. Really this is just a wrapper around
59
+ # MARC::MARC21::decode
60
+ #
61
+ # record = MARC::Record.new_from_marc(marc21)
62
+
63
+
64
+ def Record::new_from_marc(raw)
65
+ return MARC::MARC21.new().decode(raw)
66
+ end
67
+
68
+
69
+ # Handy method for returning a the MARC21 serialization for a
70
+ # MARC::Record object. Really this is just a wrapper around
71
+ # MARC::MARC21::encode
72
+ #
73
+ # marc = record.to_marc()
74
+
75
+ def to_marc
76
+ return MARC::MARC21.new().encode(self)
77
+ end
78
+
79
+
80
+ # Returns a string version of the record, suitable for printing
81
+
82
+ def to_s
83
+ str = "LEADER #{leader}\n"
84
+ for field in fields:
85
+ str += field.to_s() + "\n"
86
+ end
87
+ return str
88
+ end
89
+
90
+
91
+ # For testing if two records can be considered equal.
92
+
93
+ def ==(other)
94
+ if @leader != other.leader:
95
+ return false
96
+ elsif @fields.length != other.fields.length()
97
+ return false
98
+ else
99
+ for i in [0..@fields.length()]:
100
+ return false if @fields[i] != other.fields[i]
101
+ end
102
+ end
103
+ return true
104
+ end
105
+
106
+
107
+ # Handy for using a record in a regex:
108
+ # if record =~ /Gravity's Rainbow/ then print "Slothrop" end
109
+
110
+ def =~(regex)
111
+ return self.to_s =~ regex
112
+ end
113
+
114
+ end
115
+
116
+ end
117
+
@@ -0,0 +1,25 @@
1
+ module MARC
2
+
3
+ class Subfield
4
+ attr_accessor :code, :value
5
+
6
+ def initialize(code,value)
7
+ @code = code
8
+ @value = value
9
+ end
10
+
11
+ def ==(other)
12
+ if @code != other.code
13
+ return false
14
+ elsif @value != other.value
15
+ return false
16
+ end
17
+ return true
18
+ end
19
+
20
+ def to_s
21
+ return "$#{code}#{value}"
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,36 @@
1
+ module MARC
2
+
3
+ # A class for writing MARC records as MARC21.
4
+
5
+ class Writer
6
+
7
+ # the constructor which you must pass a file path
8
+ # or an object that responds to a write message
9
+
10
+ def initialize(file)
11
+ if file.class == String
12
+ @fh = File.new(file,"w")
13
+ elsif file.respond_to?(file)
14
+ @fh = file
15
+ else
16
+ throw "must pass in file name or handle"
17
+ end
18
+ end
19
+
20
+
21
+ # write a record to the file or handle
22
+
23
+ def write(record)
24
+ @fh.write(record.to_marc)
25
+ end
26
+
27
+
28
+ # close underlying filehandle
29
+
30
+ def close
31
+ @fh.close
32
+ end
33
+
34
+ end
35
+
36
+ end
data/lib/marc.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'marc/record'
2
+ require 'marc/field'
3
+ require 'marc/control'
4
+ require 'marc/subfield'
5
+ require 'marc/reader'
6
+ require 'marc/writer'
7
+ require 'marc/exception'
8
+ require 'marc/marc21'
data/test/batch.dat ADDED
@@ -0,0 +1 @@
1
+ 00755cam 22002414a 4500001001300000003000600013005001700019008004100036010001700077020004300094040001800137042000800155050002600163082001700189100003100206245005400237260004200291300007200333500003300405650003700438630002500475630001300500fol05731351 IMchF20000613133448.0000107s2000 nyua 001 0 eng  a 00020737  a0471383147 (paper/cd-rom : alk. paper) aDLCcDLCdDLC apcc00aQA76.73.P22bM33 200000a005.13/32211 aMartinsson, Tobias,d1976-10aActivePerl with ASP and ADO /cTobias Martinsson. aNew York :bJohn Wiley & Sons,c2000. axxi, 289 p. :bill. ;c23 cm. +e1 computer laser disc (4 3/4 in.) a"Wiley Computer Publishing." 0aPerl (Computer program language)00aActive server pages.00aActiveX.00647pam 2200241 a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002600135082001500161100002600176245006700202260003800269263000900307300001100316650003700327650002500364700001600389fol05754809 IMchF20000601115601.0000203s2000 mau 001 0 eng  a 00022023  a1565926994 aDLCcDLCdDLC apcc00aQA76.73.P22bD47 200000a005.742211 aDescartes, Alligator.10aProgramming the Perl DBI /cAlligator Descartes and Tim Bunce. aCmabridge, MA :bO'Reilly,c2000. a1111 ap. cm. 0aPerl (Computer program language) 0aDatabase management.1 aBunce, Tim.00605cam 22002054a 4500001001300000003000600013005001700019008004100036010001700077040001800094042000800112050002700120082001700147100002100164245005500185260004500240300002600285504005100311650003700362fol05843555 IMchF20000525142739.0000318s1999 cau b 001 0 eng  a 00501349  aDLCcDLCdDLC apcc00aQA76.73.P22bB763 199900a005.13/32211 aBrown, Martin C.10aPerl :bprogrammer's reference /cMartin C. Brown. aBerkeley :bOsborne/McGraw-Hill,cc1999. axix, 380 p. ;c22 cm. aIncludes bibliographical references and index. 0aPerl (Computer program language)00579cam 22002054a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002700135082001700162100002100179245005500200260004500255300003600300650003700336fol05843579 IMchF20000525142716.0000318s1999 caua 001 0 eng  a 00502116  a0072120002 aDLCcDLCdDLC apcc00aQA76.73.P22bB762 199900a005.13/32211 aBrown, Martin C.10aPerl :bthe complete reference /cMartin C. Brown. aBerkeley :bOsborne/McGraw-Hill,cc1999. axxxv, 1179 p. :bill. ;c24 cm. 0aPerl (Computer program language)00801nam 22002778a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001800156100002000174245008800194250003200282260004100314263000900355300001100364650003700375650003600412650002600448700002500474700002400499fol05848297 IMchF20000524125727.0000518s2000 mau 001 0 eng  a 00041664  a1565924193 aDLCcDLC apcc00aQA76.73.P22bG84 200000a005.2/7622211 aGuelich, Scott.10aCGI programming with Perl /cScott Guelich, Shishir Gundavaram & Gunther Birznieks. a2nd ed., expanded & updated aCambridge, Mass. :bO'Reilly,c2000. a0006 ap. cm. 0aPerl (Computer program language) 0aCGI (Computer network protocol) 0aInternet programming.1 aGundavaram, Shishir.1 aBirznieks, Gunther.00665nam 22002298a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002700130082001700157111005200174245008600226250001200312260004100324263000900365300001100374650005000385fol05865950 IMchF20000615103017.0000612s2000 mau 100 0 eng  a 00055759  a0596000138 aDLCcDLC apcc00aQA76.73.P22bP475 200000a005.13/32212 aPerl Conference 4.0d(2000 :cMonterey, Calif.)10aProceedings of the Perl Conference 4.0 :bJuly 17-20, 2000, Monterey, California. a1st ed. aCambridge, Mass. :bO'Reilly,c2000. a0006 ap. cm. 0aPerl (Computer program language)vCongresses.00579nam 22002178a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001700156100002800173245006200201260004100263263000900304300001100313650003700324fol05865956 IMchF20000615102948.0000612s2000 mau 000 0 eng  a 00055770  a1565926099 aDLCcDLC apcc00aQA76.73.P22bB43 200000a005.13/32211 aBlank-Edelman, David N.10aPerl for system administration /cDavid N. Blank-Edelman. aCambridge, Mass. :bO'Reilly,c2000. a0006 ap. cm. 0aPerl (Computer program language)00661nam 22002538a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001300109042000800122050002600130082001700156100001700173245006700190250001200257260004100269263000900310300001100319650003700330700002300367700001700390fol05865967 IMchF20000615102611.0000614s2000 mau 000 0 eng  a 00055799  a0596000278 aDLCcDLC apcc00aQA76.73.P22bW35 200000a005.13/32211 aWall, Larry.10aProgramming Perl /cLarry Wall, Tom Christiansen & Jon Orwant. a3rd ed. aCambridge, Mass. :bO'Reilly,c2000. a0007 ap. cm. 0aPerl (Computer program language)1 aChristiansen, Tom.1 aOrwant, Jon.00603cam 22002054a 4500001001300000003000600013005001700019008004100036010001700077020001500094040001800109042000800127050002600135082001700161100003200178245006000210260005700270300003300327650003700360fol05872355 IMchF20000706095105.0000315s1999 njua 001 0 eng  a 00500678  a013020868X aDLCcDLCdDLC apcc00aQA76.73.P22bL69 199900a005.13/32211 aLowe, Vincentq(Vincent D.)10aPerl programmer's interactive workbook /cVincent Lowe. aUpper Saddle River, NJ :bPrentice Hall PTP,cc1999. axx, 633 p. :bill. ;c23 cm. 0aPerl (Computer program language)00696nam 22002538a 4500001001300000003000600013005001700019008004100036010001700077020002800094040001300122042000800135050002600143082001700169100002600186245004400212260005100256263000900307300001100316500002000327650003700347650001700384650004100401fol05882032 IMchF20000707091904.0000630s2000 cau 001 0 eng  a 00058174  a0764547291 (alk. paper) aDLCcDLC apcc00aQA76.73.P22bF64 200000a005.13/32212 aFoster-Johnson, Eric.10aCross-platform Perl /cEric F. Johnson. aFoster City, CA :bIDG Books Worldwide,c2000. a0009 ap. cm. aIncludes index. 0aPerl (Computer program language) 0aWeb servers. 0aCross-platform software development.
data/test/one.dat ADDED
@@ -0,0 +1 @@
1
+ 00755cam 22002414a 4500001001300000003000600013005001700019008004100036010001700077020004300094040001800137042000800155050002600163082001700189100003100206245005400237260004200291300007200333500003300405650003700438630002500475630001300500fol05731351 IMchF20000613133448.0000107s2000 nyua 001 0 eng  a 00020737  a0471383147 (paper/cd-rom : alk. paper) aDLCcDLCdDLC apcc00aQA76.73.P22bM33 200000a005.13/32211 aMartinsson, Tobias,d1976-10aActivePerl with ASP and ADO /cTobias Martinsson. aNew York :bJohn Wiley & Sons,c2000. axxi, 289 p. :bill. ;c23 cm. +e1 computer laser disc (4 3/4 in.) a"Wiley Computer Publishing." 0aPerl (Computer program language)00aActive server pages.00aActiveX.
data/test/tc_field.rb ADDED
@@ -0,0 +1,81 @@
1
+ require 'test/unit'
2
+ require 'marc'
3
+
4
+ class TestField < Test::Unit::TestCase
5
+
6
+ def test_tag
7
+ f1 = MARC::Field.new('100')
8
+ assert_equal('100', f1.tag)
9
+ f2 = MARC::Field.new(tag='100')
10
+ assert_equal('100', f2.tag)
11
+ assert_equal(f1, f2)
12
+ f3 = MARC::Field.new('245')
13
+ assert_not_equal(f1, f3)
14
+ end
15
+
16
+ def test_indicators
17
+ f1 = MARC::Field.new('100', '0', '1')
18
+ assert_equal('0', f1.indicator1)
19
+ assert_equal('1', f1.indicator2)
20
+ f2 = MARC::Field.new(tag='100',i1='0',i2='1')
21
+ assert_equal('0', f2.indicator1)
22
+ assert_equal('1', f2.indicator2)
23
+ assert_equal(f1, f2)
24
+ f3 = MARC::Field.new(tag='100', i1='1', i2='1')
25
+ assert_not_equal(f1, f3)
26
+ end
27
+
28
+ def test_subfields
29
+ f1 = MARC::Field.new('100', '0', '1',
30
+ MARC::Subfield.new('a', 'Foo'),
31
+ MARC::Subfield.new('b', 'Bar') )
32
+ assert_equal("100 01 $aFoo$bBar", f1.to_s)
33
+ f2 = MARC::Field.new('100', '0', '1',
34
+ MARC::Subfield.new('a', 'Foo'),
35
+ MARC::Subfield.new('b', 'Bar') )
36
+ assert_equal(f1,f2)
37
+ f3 = MARC::Field.new('100', '0', '1',
38
+ MARC::Subfield.new('a', 'Foo'),
39
+ MARC::Subfield.new('b', 'Bez') )
40
+ assert_not_equal(f1,f3)
41
+ end
42
+
43
+ def test_subfield_shorthand
44
+ f = MARC::Field.new('100', '0', '1', ['a', 'Foo'], ['b', 'Bar'])
45
+ assert_equal('100 01 $aFoo$bBar', f.to_s)
46
+ end
47
+
48
+
49
+ def test_iterator
50
+ field = MARC::Field.new('100','0','1', ['a', 'Foo'],['b', 'Bar'],
51
+ ['a', 'Bez'])
52
+ count = 0
53
+ field.each {|x| count += 1}
54
+ assert_equal(count,3)
55
+ end
56
+
57
+ def test_lookup_shorthand
58
+ f = MARC::Field.new('100', '0', '1', ['a', 'Foo'], ['b', 'Bar'])
59
+ assert_equal(f['b'], 'Bar')
60
+ end
61
+
62
+ def test_control
63
+ control = MARC::Control.new('005','foobarbaz')
64
+ assert_equal(control.to_s,'005 foobarbaz')
65
+ end
66
+
67
+ def test_field_as_control
68
+ assert_raise(MARC::Exception) do
69
+ # can't have a field with a tag < 010
70
+ field = MARC::Field.new('007')
71
+ end
72
+ end
73
+
74
+ def test_control_as_field
75
+ assert_raise(MARC::Exception) do
76
+ # can't have a control with a tag > 009
77
+ f = MARC::Control.new('245')
78
+ end
79
+ end
80
+
81
+ end
data/test/tc_reader.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'test/unit'
2
+ require 'marc'
3
+
4
+ class ReaderTest < Test::Unit::TestCase
5
+
6
+ def test_batch
7
+ reader = MARC::Reader.new('test/batch.dat')
8
+ count = 0
9
+ reader.each { count += 1 }
10
+ assert_equal(count, 10)
11
+ end
12
+
13
+ def test_search
14
+ reader = MARC::Reader.new('test/batch.dat')
15
+ records = reader.find_all { |r| r =~ /Perl/ }
16
+ assert_equal(records.length,10)
17
+
18
+ reader = MARC::Reader.new('test/batch.dat')
19
+ records = reader.find_all { |r| r['245'] =~ /Perl/ }
20
+ assert_equal(records.length,10)
21
+
22
+ reader = MARC::Reader.new('test/batch.dat')
23
+ records = reader.find_all { |r| r['245']['a'] =~ /Perl/ }
24
+ assert_equal(records.length,10)
25
+
26
+ reader = MARC::Reader.new('test/batch.dat')
27
+ records = reader.find_all { |r| r =~ /Foo/ }
28
+ assert_equal(records.length,0)
29
+ end
30
+
31
+ end
data/test/tc_record.rb ADDED
@@ -0,0 +1,55 @@
1
+ require 'test/unit'
2
+ require 'marc'
3
+
4
+ class TestRecord < Test::Unit::TestCase
5
+
6
+ def test_constructor
7
+ r = MARC::Record.new()
8
+ assert_equal(r.class, MARC::Record)
9
+ end
10
+
11
+ def test_append_field
12
+ r = get_record()
13
+ assert_equal(r.fields.length(), 2)
14
+ end
15
+
16
+ def test_iterator
17
+ r = get_record()
18
+ count = 0
19
+ r.each {|f| count += 1}
20
+ assert_equal(count,2)
21
+ end
22
+
23
+ def test_decode
24
+ raw = IO.read('test/one.dat')
25
+ r = MARC::Record::new_from_marc(raw)
26
+ assert_equal(r.class, MARC::Record)
27
+ assert_equal(r.leader,'00755cam 22002414a 45000')
28
+ assert_equal(r.fields.length(), 18)
29
+ assert_equal(r.find {|f| f.tag == '245'}.to_s,
30
+ '245 10 $aActivePerl with ASP and ADO /$cTobias Martinsson.')
31
+ end
32
+
33
+ def test_encode
34
+ r1 = MARC::Record.new()
35
+ r1.append(MARC::Field.new('100','2','0', ['a','Thomas, Dave']))
36
+ r1.append(MARC::Field.new('245','0','0', ['a','Pragmatic Programmer']))
37
+ raw = r1.to_marc()
38
+ r2 = MARC::Record::new_from_marc(raw)
39
+ assert_equal(r1, r2)
40
+ end
41
+
42
+ def test_lookup_shorthand
43
+ r = get_record
44
+ assert_equal(r['100']['a'], 'Thomas, Dave')
45
+ end
46
+
47
+ def get_record
48
+ r = MARC::Record.new()
49
+ r.append(MARC::Field.new('100', '2', '0', ['a', 'Thomas, Dave']))
50
+ r.append(MARC::Field.new('245', '0', '4', ['The Pragmatic Programmer']))
51
+ return r
52
+ end
53
+
54
+
55
+ end
@@ -0,0 +1,18 @@
1
+ require 'test/unit'
2
+ require 'marc/subfield'
3
+
4
+ class SubfieldTest < Test::Unit::TestCase
5
+
6
+ def test_ok
7
+ s = MARC::Subfield.new('a','foo')
8
+ assert_equal(s.code,'a')
9
+ assert_equal(s.value,'foo')
10
+ end
11
+
12
+ def test_equals
13
+ s1 =MARC::Subfield.new('a','foo')
14
+ s2 =MARC::Subfield.new('a','foo')
15
+ assert_equal(s1,s2)
16
+ end
17
+
18
+ end
data/test/tc_writer.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'test/unit'
2
+ require 'marc'
3
+
4
+ class WriterTest < Test::Unit::TestCase
5
+
6
+ def test_writer()
7
+ writer = MARC::Writer.new('test/writer.dat')
8
+ record = MARC::Record.new()
9
+ record.append(MARC::Field.new('245', '0', '1', ['a','foo']))
10
+ writer.write(record)
11
+ writer.close()
12
+
13
+ # read it back to make sure
14
+ reader = MARC::Reader.new('test/writer.dat')
15
+ records = reader.entries()
16
+ assert_equal(records.length(), 1)
17
+ assert_equal(records[0], record)
18
+
19
+ # cleanup
20
+ File.unlink('test/writer.dat')
21
+ end
22
+
23
+ end
data/test/ts_marc.rb ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # local marc library gets tested
4
+ # not already installed one
5
+ $LOAD_PATH.unshift("lib")
6
+
7
+ require 'test/unit'
8
+ require 'test/tc_subfield'
9
+ require 'test/tc_field'
10
+ require 'test/tc_record'
11
+ require 'test/tc_reader'
12
+ require 'test/tc_writer'
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: marc
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.2
7
+ date: 2005-10-17 00:00:00 -05:00
8
+ summary: A ruby library for working with Machine Readable Cataloging
9
+ require_paths:
10
+ - lib
11
+ email: ehs@pobox.com
12
+ homepage: http://www.textualize.com/marc
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: marc
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ signing_key:
28
+ cert_chain:
29
+ authors:
30
+ - Ed Summers
31
+ files:
32
+ - lib/marc
33
+ - lib/marc.rb
34
+ - lib/marc/control.rb
35
+ - lib/marc/exception.rb
36
+ - lib/marc/field.rb
37
+ - lib/marc/marc21.rb
38
+ - lib/marc/reader.rb
39
+ - lib/marc/record.rb
40
+ - lib/marc/subfield.rb
41
+ - lib/marc/writer.rb
42
+ - test/batch.dat
43
+ - test/one.dat
44
+ - test/tc_field.rb
45
+ - test/tc_reader.rb
46
+ - test/tc_record.rb
47
+ - test/tc_subfield.rb
48
+ - test/tc_writer.rb
49
+ - test/ts_marc.rb
50
+ test_files:
51
+ - test/ts_marc.rb
52
+ rdoc_options: []
53
+ extra_rdoc_files: []
54
+ executables: []
55
+ extensions: []
56
+ requirements: []
57
+ dependencies: []