Permalink
Browse files

Refactor + add specs based on dummy eptrn file

  • Loading branch information...
1 parent 4bb4574 commit 5904950f993390da54c37e09b05c8cc64a17df78 Anthony Zacharakis committed Mar 31, 2013
Showing with 186 additions and 88 deletions.
  1. +6 −42 Gemfile.lock
  2. +12 −7 config/eptrn.yml
  3. +2 −4 lib/paxmex.rb
  4. +0 −5 lib/paxmex/epraw_parser.rb
  5. +0 −5 lib/paxmex/eptrn_parser.rb
  6. +41 −20 lib/paxmex/parser.rb
  7. +5 −1 lib/paxmex/schema.rb
  8. +1 −4 paxmex.gemspec
  9. +114 −0 spec/parser_spec.rb
  10. +5 −0 spec/support/dummy_eptrn_raw
View
@@ -2,14 +2,10 @@ PATH
remote: .
specs:
paxmex (0.0.1)
- rails (~> 3.2.12)
GEM
remote: http://rubygems.org/
specs:
- actionmailer (3.2.12)
- actionpack (= 3.2.12)
- mail (~> 2.4.4)
actionpack (3.2.12)
activemodel (= 3.2.12)
activesupport (= 3.2.12)
@@ -23,18 +19,9 @@ GEM
activemodel (3.2.12)
activesupport (= 3.2.12)
builder (~> 3.0.0)
- activerecord (3.2.12)
- activemodel (= 3.2.12)
- activesupport (= 3.2.12)
- arel (~> 3.0.2)
- tzinfo (~> 0.3.29)
- activeresource (3.2.12)
- activemodel (= 3.2.12)
- activesupport (= 3.2.12)
activesupport (3.2.12)
i18n (~> 0.6)
multi_json (~> 1.0)
- arel (3.0.2)
builder (3.0.4)
diff-lcs (1.1.3)
erubis (2.7.0)
@@ -45,28 +32,14 @@ GEM
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
json (1.7.7)
- mail (2.4.4)
- i18n (>= 0.4.0)
- mime-types (~> 1.16)
- treetop (~> 1.4.8)
- mime-types (1.21)
multi_json (1.6.1)
- polyglot (0.3.3)
rack (1.4.5)
rack-cache (1.2)
rack (>= 0.4)
rack-ssl (1.3.3)
rack
rack-test (0.6.2)
rack (>= 1.0)
- rails (3.2.12)
- actionmailer (= 3.2.12)
- actionpack (= 3.2.12)
- activerecord (= 3.2.12)
- activeresource (= 3.2.12)
- activesupport (= 3.2.12)
- bundler (~> 1.0)
- railties (= 3.2.12)
railties (3.2.12)
actionpack (= 3.2.12)
activesupport (= 3.2.12)
@@ -77,35 +50,26 @@ GEM
rake (10.0.3)
rdoc (3.12.1)
json (~> 1.4)
+ rspec (2.12.0)
+ rspec-core (~> 2.12.0)
+ rspec-expectations (~> 2.12.0)
+ rspec-mocks (~> 2.12.0)
rspec-core (2.12.2)
rspec-expectations (2.12.1)
diff-lcs (~> 1.1.3)
rspec-mocks (2.12.2)
- rspec-rails (2.12.2)
- actionpack (>= 3.0)
- activesupport (>= 3.0)
- railties (>= 3.0)
- rspec-core (~> 2.12.0)
- rspec-expectations (~> 2.12.0)
- rspec-mocks (~> 2.12.0)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
- sqlite3 (1.3.7)
thor (0.17.0)
tilt (1.3.3)
- treetop (1.4.12)
- polyglot
- polyglot (>= 0.3.1)
- tzinfo (0.3.35)
PLATFORMS
ruby
DEPENDENCIES
- paxmex!
jquery-rails
- rspec-rails
- sqlite3
+ paxmex!
+ rspec
View
@@ -24,14 +24,15 @@ DETAIL_RECORD:
RECURRING: true
TYPE_FIELD: [43, 44]
TYPE_MAPPING:
- '00': 'SUMMARY_RECORD'
- '10': 'SUMMARY_OF_CHARGE_DETAIL_RECORD'
- '11': 'RECORD_OF_CHARGE_DETAIL_RECORD'
- '20': 'CHARGEBACK_DETAIL_RECORD'
- '30': 'ADJUSTMENT_DETAIL_RECORD'
- '50': 'OTHER_FEES_AND_REVENUES_DETAIL_RECORDS'
+ '00': SUMMARY_RECORD
+ '10': SUMMARY_OF_CHARGE_DETAIL_RECORD
+ '11': RECORD_OF_CHARGE_DETAIL_RECORD
+ '20': CHARGEBACK_DETAIL_RECORD
+ '30': ADJUSTMENT_DETAIL_RECORD
+ '50': OTHER_FEES_AND_REVENUES_DETAIL_RECORDS
TYPES:
SUMMARY_OF_CHARGE_DETAIL_RECORD:
+ RECURRING: true
FIELDS:
AMEX_PAYEE_NUMBER: [0, 9]
AMEX_SE_NUMBER: [10, 19]
@@ -55,6 +56,7 @@ DETAIL_RECORD:
CPC_INDICATOR: [166, 166]
AMEX_RO_COUNT_POA: [182, 188]
RECORD_OF_CHARGE_DETAIL_RECORD:
+ RECURRING: true
FIELDS:
TLRR_AMEX_PAYEE_NUMBER: [0, 9]
TLRR_AMEX_SE_NUMBER: [10, 19]
@@ -78,10 +80,11 @@ DETAIL_RECORD:
NON_COMPLIANT_INDICATOR: [183, 183]
NON_COMPLIANT_ERROR_CODE_1: [184, 187]
NON_COMPLIANT_ERROR_CODE_2: [188, 191]
- NON_COMPLIANT_ERROR_CODE_3: [192, 185]
+ NON_COMPLIANT_ERROR_CODE_3: [192, 195]
NON_COMPLIANT_ERROR_CODE_4: [196, 199]
NON_SWIPED_INDICATOR: [200, 200]
CHARGEBACK_DETAIL_RECORD:
+ RECURRING: true
FIELDS:
AMEX_PAYEE_NUMBER: [0, 9]
AMEX_SE_NUMBER: [10, 19]
@@ -102,6 +105,7 @@ DETAIL_RECORD:
SERVICE_FEE_RATE: [122, 126]
CHARGEBACK_REASON: [143, 422]
ADJUSTMENT_DETAIL_RECORD:
+ RECURRING: true
FIELDS:
AMEX_PAYEE_NUMBER: [0, 9]
AMEX_SE_NUMBER: [10, 19]
@@ -121,6 +125,7 @@ DETAIL_RECORD:
CARDMEMBER_NUMBER: [125, 141]
ADJUSTMENT_REASON: [142, 421]
OTHER_FEES_AND_REVENUES_DETAIL_RECORDS:
+ RECURRING: true
FIELDS:
AMEX_PAYEE_NUMBER: [0, 9]
AMEX_SE_NUMBER: [10, 19]
View
@@ -1,13 +1,11 @@
module Paxmex
require 'paxmex/parser'
- require 'paxmex/eptrn_parser'
- require 'paxmex/epraw_parser'
def self.parse_eptrn(file)
- Paxmex::EptrnParser.new(file).parse
+ Parser.new(file, schema: 'eptrn').parse
end
def self.parse_epraw(file)
- Paxmex::EptrawParser.new(file).parse
+ Parser.new(file, schema: 'epraw').parse
end
end
@@ -1,5 +0,0 @@
-class Paxmex::EprawParser < Paxmex::Parser
- def self.schema_hash
- @schema_hash ||= YAML::load(File.open('config/eptraw.yml'))
- end
-end
@@ -1,5 +0,0 @@
-class Paxmex::EptrnParser < Paxmex::Parser
- def self.schema_hash
- @schema_hash ||= YAML::load(File.open('config/eptrn.yml'))
- end
-end
View
@@ -1,10 +1,16 @@
require 'yaml'
-require 'schema'
+require 'paxmex/schema'
class Paxmex::Parser
- def initialize(path)
+ SCHEMATA = %w(epraw eptrn).reduce({}) { |h, fn| h.merge(fn => YAML::load(File.open("config/#{fn}.yml"))) }
+
+ def initialize(path, opts = {})
@path = path
- @schema = Paxmex::Schema.new(self.class.schema_hash)
+ @schema_key = opts[:schema]
+ end
+
+ def schema
+ @schema ||= Paxmex::Schema.new(SCHEMATA[@schema_key])
end
def raw
@@ -14,40 +20,55 @@ def raw
def parse
return @parsed if @parsed
- content = raw.dup
+ content = raw.split("\n")
+ # Parse the trailing section first so that we don't need
+ # to consider it when parsing recurring sections
trailer_section = schema.sections.detect(&:trailer?)
- trailer_content = content.slice!(content.length - trailer_section.length..content.length)
+ trailer_content = [content.slice!(-1)]
@parsed = parse_section(content: trailer_content, section: trailer_section)
- (schema.sections - [trailer_section]).each do |section|
- section_content = section.recurring? ? content : content.slice!(0..section.length)
- parsed_section = parse_section(content: section_content, section: section)
- @parsed.merge!(parsed_section)
+ schema.sections.reject(&:trailer?).each do |section|
+ @parsed.merge!(
+ parse_section(
+ content: section.recurring? ? content : [content.slice!(0)],
+ section: section))
end
@parsed
end
private
- attr_reader :schema
-
def parse_section(opts = {})
raise 'Content must be provided' unless content = opts[:content]
raise 'Section must be provided' unless section = opts[:section]
- if section.abstract?
- start, final = section.type_field
- section_type = content[start..final]
- section = section.section_for_type(section_type)
- end
+ result = {}
+ abstract_section = section if section.abstract?
- result = {section.key => {}}
- section.fields.each do |field_name, positions|
- start, final = positions
- result[section.key][field_name] = content[start..final]
+ content.each do |section_content|
+ if abstract_section
+ start, final = abstract_section.type_field
+ section_type = section_content[start..final]
+ section = abstract_section.section_for_type(section_type)
+ end
+
+ result[section.key] ||= [] if section.recurring?
+
+ p = {}
+ section.fields.each do |field_name, positions|
+ start, final = positions
+ p[field_name] = section_content[start..final]
+ end
+
+ if section.recurring?
+ result[section.key] << p
+ else
+ result[section.key] = p
+ end
end
+
result
end
end
View
@@ -7,6 +7,10 @@ def sections
@sections ||= @schema_hash.map { |k, v| Section.new(k, v) }
end
+ def to_h
+ @schema_hash
+ end
+
class Section
BLOCK_LENGTH = 450
@@ -50,7 +54,7 @@ def section_for_type(type)
end
def length
- recurring? ? nil : BLOCK_LENGTH
+ BLOCK_LENGTH
end
private
View
@@ -15,8 +15,5 @@ Gem::Specification.new do |s|
s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile", "README.md"]
- s.add_dependency "rails", "~> 3.2.12"
-
- s.add_development_dependency "sqlite3"
- s.add_development_dependency "rspec-rails"
+ s.add_development_dependency "rspec"
end
Oops, something went wrong.

0 comments on commit 5904950

Please sign in to comment.