class X12::Base

Base class for {Segment}, {Composite}, and {Loop}. Contains setable segment_separator, field_separator, and composite_separator fields.

Attributes

composite_separator[RW]
field_separator[RW]
name[R]
next_repeat[RW]
nodes[RW]
parsed_str[RW]
repeats[R]
segment_separator[RW]

Public Class Methods

new(name, arr, repeats = nil) click to toggle source

Creates a new base element with a given name, array of sub-elements, and array of repeats if any.

@return [void]

# File lib/x12/base.rb, line 14
def initialize(name, arr, repeats = nil)
  @nodes = arr
  @name = name
  @repeats = repeats
  @next_repeat = nil # Next repeat of the same element, if any
  @parsed_str = nil

  @segment_separator   = '~'
  @field_separator     = '*'
  @composite_separator = ':'

  # puts "Created #{name} #{object_id} #{self.class}  "
end

Public Instance Methods

[](*args) click to toggle source

The main method implementing Ruby-like access methods for repeating elements.

# File lib/x12/base.rb, line 156
def [](*args)
  # puts "squares #{args.inspect}"
  return self.to_a[args[0]] || EMPTY
end
do_repeats(s) click to toggle source

Try to parse the current element one more time if required. Returns the rest of the string or the same string if no more repeats are found or required.

# File lib/x12/base.rb, line 59
def do_repeats(s)
  if self.repeats.end > 1
    possible_repeat = self.dup
    p_s = possible_repeat.parse(s)
    if p_s
      s = p_s
      self.next_repeat = possible_repeat
    end
  end
  s
end
dup() click to toggle source

Make a deep copy of the element.

# File lib/x12/base.rb, line 81
def dup
  n = clone
  n.set_empty!
  n.nodes = n.nodes.dup
  n.nodes.each_index{|i|
    n.nodes[i] = n.nodes[i].dup
    n.nodes[i].set_empty!
  }
  # puts "Duped #{self.class} #{self.name} #{self.object_id} #{super.object_id} -> #{n.name} #{n.super.object_id} #{n.object_id} "
  n
end
find(e) click to toggle source

Recursively find a sub-element, which also has to be of type Base.

# File lib/x12/base.rb, line 94
def find(e)
  # puts "Finding [#{e}] in #{self.class} #{name}"
  case self
    when X12::Loop
    # Breadth first
    res = nodes.find { |i| e == i.name }
    return res if res
    # Depth now
    nodes.each{ |i|
      res = i.find(e) if i.is_a?(X12::Loop)
      return res unless res.nil? or EMPTY == res # otherwise keep looping
    }
    when X12::Segment
    return find_field(e).to_s
  end
  return EMPTY
end
has_content?() click to toggle source

Check if any of the fields has been set yet.

# File lib/x12/base.rb, line 177
def has_content?
  self.nodes.find{ |i| i.has_content? }
end
inspect() click to toggle source

Formats a printable string containing the base element's content.

@return [String]

# File lib/x12/base.rb, line 31
def inspect
  "#{self.class.to_s.sub(/^.*::/, '')} (#{name}) #{repeats} #{super.inspect[1..-2]} =<#{parsed_str}, #{next_repeat.inspect}> ".gsub(/\\*\"/, '"')
end
method_missing(meth, *args) { |res| ... } click to toggle source

The main method implementing Ruby-like access methods for nested elements.

# File lib/x12/base.rb, line 130
def method_missing(meth, *args, &block)
  str = meth.id2name
  str = str[1..str.length] if str =~ /^_\d+$/ # to avoid pure number names like 270, 997, etc.
  # puts "Missing #{str}"
  if str =~ /=$/
    # Assignment
    str.chop!
    # puts str
    case self
    when X12::Segment
      res = find_field(str)
      throw Exception.new("No field '#{str}' in segment '#{self.name}'") if EMPTY == res
      res.content = args[0].to_s
      # puts res.inspect
    else
      throw Exception.new("Illegal assignment to #{meth} of #{self.class}")
    end
  else
    # Retrieval
    res = find(str)
    yield res if block_given?
    res
  end
end
repeat() { |res| ... } click to toggle source

Adds a repeat to a segment or loop. Returns a new segment/loop or self if empty.

# File lib/x12/base.rb, line 183
def repeat
  res = if self.has_content? # Do not repeat an empty segment
          last_repeat = self.to_a[-1]
          last_repeat.next_repeat = last_repeat.dup
        else
          self
        end
  yield res if block_given?
  res
end
set_empty!() click to toggle source

Empty out the current element.

@return [void]

# File lib/x12/base.rb, line 74
def set_empty!
  @next_repeat = nil
  @parsed_str = nil
  self
end
show(ind = '') click to toggle source

Prints a tree-like representation of the element.

@return [void]

# File lib/x12/base.rb, line 38
def show(ind = '')
  count = 0
  self.to_a.each{|i|
    # puts "#{ind}#{i.name} #{i.object_id} #{i.super.object_id} [#{count}]: #{i.parsed_str} #{i.super.class}"
    puts "#{ind}#{i.name} [#{count}]: #{i.to_s.sub(/^(.{30})(.*?)(.{30})$/, '\1...\3')}"
    # Force parsing a segment
    if i.is_a?(X12::Segment) && i.nodes[0]
      i.find_field(i.nodes[0].name)
    end
    i.nodes.each{|j|
      case
      when j.is_a?(X12::Base)  then j.show(ind + '  ')
      when j.is_a?(X12::Field) then puts "#{ind}  #{j.name} -> '#{j}'"
      end
    }
    count += 1
  }
end
size() click to toggle source

Returns number of repeats. @return [Integer]

# File lib/x12/base.rb, line 172
def size
  return self.to_a.size
end
to_a() click to toggle source

Present self and all repeats as an array with self being #0.

# File lib/x12/base.rb, line 113
def to_a
  res = [self]
  nr = self.next_repeat
  while nr
    res << nr
    nr = nr.next_repeat
  end
  res
end
to_s() click to toggle source

Returns a parsed string representation of the element. @return [String]

# File lib/x12/base.rb, line 125
def to_s
  @parsed_str || ''
end
with() { |self| ... } click to toggle source

Yields to accompanying block passing self as a parameter.

# File lib/x12/base.rb, line 162
def with(&block)
  if block_given?
    yield self
  else
    throw Exception.new("Method 'with' requires a block.")
  end
end