Class: MARC::Writer

Inherits:
Object
  • Object
show all
Defined in:
lib/marc/writer.rb,
lib/marc/writer-NEW.rb

Overview

A class for writing MARC records as MARC21.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ Writer

the constructor which you must pass a file path or an object that responds to a write message



32
33
34
35
36
37
38
39
40
41
# File 'lib/marc/writer.rb', line 32

def initialize(file)
  if file.class == String
    @fh = File.new(file,"w")
  elsif file.respond_to?('write')
    @fh = file
  else
    throw "must pass in file name or handle"
  end
  self.allow_oversized = false
end

Instance Attribute Details

#allow_oversizedObject

Returns the value of attribute allow_oversized.



27
28
29
# File 'lib/marc/writer.rb', line 27

def allow_oversized
  @allow_oversized
end

Class Method Details

.encode(record) ⇒ Object

a static method that accepts a MARC::Record object and returns the record encoded as MARC21 in transmission format



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
# File 'lib/marc/writer.rb', line 63

def self.encode(record, allow_oversized = false)
  directory = ''
  fields = ''
  offset = 0
  for field in record.fields

    # encode the field
    field_data = ''
    if field.class == MARC::DataField 
      warn("Warn:  Missing indicator") unless field.indicator1 && field.indicator2
      field_data = (field.indicator1 || " ") + (field.indicator2 || " ")
      for s in field.subfields
        field_data += SUBFIELD_INDICATOR + s.code + s.value
      end
    elsif field.class == MARC::ControlField
      field_data = field.value
    end
    field_data += END_OF_FIELD

    # calculate directory entry for the field
    field_length = (field_data.respond_to?(:bytesize) ?
      field_data.bytesize() :
      field_data.length())
    directory += sprintf("%03s", field.tag) + format_byte_count(field_length, allow_oversized, 4) + format_byte_count(offset, allow_oversized)


    # add field to data for other fields
    fields += field_data 

    # update offset for next field
    offset += field_length
  end

  # determine the base (leader + directory)
  base = record.leader + directory + END_OF_FIELD

  # determine complete record
  marc = base + fields + END_OF_RECORD

  # update leader with the byte offest to the end of the directory
  bytesize = base.respond_to?(:bytesize) ? base.bytesize() : base.length()
  marc[12..16] = format_byte_count(bytesize, allow_oversized)
  

  # update the record length
  bytesize = marc.respond_to?(:bytesize) ? marc.bytesize() : marc.length()
  marc[0..4] = format_byte_count(bytesize, allow_oversized)      

  # store updated leader in the record that was passed in
  record.leader = marc[0..LEADER_LENGTH-1]

  # return encoded marc
  return marc
end

.format_byte_count(number, num_digits = 5) ⇒ Object

Formats numbers for insertion into marc binary slots. These slots only allow so many digits (and need to be left-padded with spaces to that number of digits). If the number is too big, either an exception will be raised, or we’ll return all 0’s to proper number of digits.

first arg is number, second is boolean whether to allow oversized, third is max digits (default 5)



126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/marc/writer.rb', line 126

def self.format_byte_count(number, allow_oversized, num_digits=5)
  formatted = sprintf("%0#{num_digits}i", number)
  if formatted.length > num_digits
    # uh, oh, we've exceeded our max. Either zero out
    # or raise, depending on settings.
    if allow_oversized
      formatted = sprintf("%0#{num_digits}i", 0)
    else
      raise MARC::Exception.new("Can't write MARC record in binary format, as a length/offset value of #{number} is too long for a #{num_digits}-byte slot.")
    end
  end
  return formatted
end

Instance Method Details

#closeObject

close underlying filehandle



53
54
55
# File 'lib/marc/writer.rb', line 53

def close
  @fh.close
end

#write(record) ⇒ Object

write a record to the file or handle



46
47
48
# File 'lib/marc/writer.rb', line 46

def write(record)
  @fh.write(MARC::Writer.encode(record, self.allow_oversized))
end