Class: X12::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/x12/base.rb

Overview

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

Direct Known Subclasses

Composite, Empty, Loop, Segment

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, arr, repeats = nil) ⇒ void

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



14
15
16
17
18
19
20
21
22
23
24
25
26
# 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

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object

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



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# 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

Instance Attribute Details

#composite_separatorObject

Returns the value of attribute composite_separator.



8
9
10
# File 'lib/x12/base.rb', line 8

def composite_separator
  @composite_separator
end

#field_separatorObject

Returns the value of attribute field_separator.



8
9
10
# File 'lib/x12/base.rb', line 8

def field_separator
  @field_separator
end

#nameObject (readonly)

Returns the value of attribute name.



7
8
9
# File 'lib/x12/base.rb', line 7

def name
  @name
end

#next_repeatObject

Returns the value of attribute next_repeat.



9
10
11
# File 'lib/x12/base.rb', line 9

def next_repeat
  @next_repeat
end

#nodesObject

Returns the value of attribute nodes.



9
10
11
# File 'lib/x12/base.rb', line 9

def nodes
  @nodes
end

#parsed_strObject

Returns the value of attribute parsed_str.



9
10
11
# File 'lib/x12/base.rb', line 9

def parsed_str
  @parsed_str
end

#repeatsObject (readonly)

Returns the value of attribute repeats.



7
8
9
# File 'lib/x12/base.rb', line 7

def repeats
  @repeats
end

#segment_separatorObject

Returns the value of attribute segment_separator.



8
9
10
# File 'lib/x12/base.rb', line 8

def segment_separator
  @segment_separator
end

Instance Method Details

#[](*args) ⇒ Object

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



156
157
158
159
# File 'lib/x12/base.rb', line 156

def [](*args)
  # puts "squares #{args.inspect}"
  return self.to_a[args[0]] || EMPTY
end

#do_repeats(s) ⇒ Object

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.



59
60
61
62
63
64
65
66
67
68
69
# 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

#dupObject

Make a deep copy of the element.



81
82
83
84
85
86
87
88
89
90
91
# 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) ⇒ Object

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



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# 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?Boolean

Check if any of the fields has been set yet.

Returns:

  • (Boolean)


177
178
179
# File 'lib/x12/base.rb', line 177

def has_content?
  self.nodes.find{ |i| i.has_content? }
end

#inspectString

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

Returns:

  • (String)


31
32
33
# 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

#repeat {|res| ... } ⇒ Object

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

Yields:

  • (res)


183
184
185
186
187
188
189
190
191
192
# 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!void

This method returns an undefined value.

Empty out the current element.



74
75
76
77
78
# File 'lib/x12/base.rb', line 74

def set_empty!
  @next_repeat = nil
  @parsed_str = nil
  self
end

#show(ind = '') ⇒ void

This method returns an undefined value.

Prints a tree-like representation of the element.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 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

#sizeInteger

Returns number of repeats.

Returns:

  • (Integer)


172
173
174
# File 'lib/x12/base.rb', line 172

def size
  return self.to_a.size
end

#to_aObject

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



113
114
115
116
117
118
119
120
121
# 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_sString

Returns a parsed string representation of the element.

Returns:

  • (String)


125
126
127
# File 'lib/x12/base.rb', line 125

def to_s
  @parsed_str || ''
end

#with(&block) ⇒ Object

Yields to accompanying block passing self as a parameter.



162
163
164
165
166
167
168
# 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