USPS-intelligent-barcode 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,24 +1,23 @@
1
- # USPS-intelligent-barcode
1
+ = USPS-intelligent-barcode
2
2
 
3
3
  USPS-intelligent-barcode is a pure ruby gem to generate a USPS
4
4
  Intelligent Mail Barcode. More specifically, it generates the string
5
- of characters you should print using one of the [USPS Intelligent
6
- Barcode fonts](https://ribbs.usps.gov/onecodesolution/download.cfm).
5
+ of characters you should print using one of the {USPS Intelligent
6
+ Barcode fonts}[https://ribbs.usps.gov/onecodesolution/download.cfm].
7
7
 
8
- ## FORKED FROM
8
+ == FORKED FROM
9
9
 
10
- This project was forked from :
10
+ This project was forked from
11
+ https://github.com/rtlong/USPS-intelligent-barcode by Ryan Taylor
12
+ Long, in order to add tests and refactor. It is _not_ a drop-in
13
+ replacement: I renamed most methods and classes, and eliminated the
14
+ #draw method.
11
15
 
12
- [rtlong/USPS-intellient-barcode](https://github.com/rtlong/USPS-intelligent-barcode)
13
- (github) by Ryan Taylor Long, in order to add tests and refactor. It
14
- is _not_ a drop-in replacement: I renamed most methods and classes,
15
- and eliminated the #draw method.
16
-
17
- ## INSTALL
16
+ == INSTALL
18
17
 
19
18
  $ gem install USPS-intelligent-barcode
20
19
 
21
- ## EXAMPLE
20
+ == EXAMPLE
22
21
 
23
22
  #!/usr/bin/env ruby
24
23
 
@@ -38,20 +37,20 @@ and eliminated the #draw method.
38
37
  p barcode.barcode_letters
39
38
  # => "AADTFFDFTDADTAADAATFDTDDAAADDTDTTDAFADADDDTFFFDDTTTADFAAADFTDAADA"
40
39
 
41
- ## STANDARD
40
+ == STANDARD
42
41
 
43
42
  This gem is based upon standard
44
- [USPS-B-3200G](https://ribbs.usps.gov/intelligentmail_mailpieces/documents/tech_guides/SPUSPSG.pdf)
43
+ {USPS-B-3200G}[https://ribbs.usps.gov/intelligentmail_mailpieces/documents/tech_guides/SPUSPSG.pdf]
45
44
 
46
- ## RUBY VERSIONS
45
+ == RUBY VERSIONS
47
46
 
48
47
  The tests are known to pass in MRI 1.8.7 and MRI 1.9.3
49
48
 
50
- ## WHOAMI
49
+ == WHOAMI
51
50
 
52
51
  Wayne Conrad <wconrad@yagni.com>
53
52
 
54
- ## CREDITS
53
+ == CREDITS
55
54
 
56
55
  Thanks to Ryan Taylor Long for his original work, without which I
57
56
  would have been lost in the USPS specification.
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "USPS-intelligent-barcode"
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Wayne Conrad"]
@@ -14,13 +14,13 @@ Gem::Specification.new do |s|
14
14
  s.email = "wayne@databill.com"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE.md",
17
- "README.md"
17
+ "README.rdoc"
18
18
  ]
19
19
  s.files = [
20
20
  "Gemfile",
21
21
  "Gemfile.lock",
22
22
  "LICENSE.md",
23
- "README.md",
23
+ "README.rdoc",
24
24
  "Rakefile",
25
25
  "USPS-intelligent-barcode.gemspec",
26
26
  "VERSION",
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
@@ -1,15 +1,41 @@
1
+ # The namespace for everything in this gem.
2
+
1
3
  module Imb
2
4
 
5
+ # This class represents a barcode
6
+
3
7
  class Barcode
4
8
 
5
9
  include Memoizer
6
10
 
11
+ # The barcode id, an instance of BarcodeId
7
12
  attr_reader :barcode_id
13
+
14
+ # The service type, an instance of ServiceType
8
15
  attr_reader :service_type
16
+
17
+ # The mailer id, an instance of MailerId
9
18
  attr_reader :mailer_id
19
+
20
+ # The serial number, and instance of SerialNumber
10
21
  attr_reader :serial_number
22
+
23
+ # The routing code, an instance of RoutingCode
11
24
  attr_reader :routing_code
12
25
 
26
+ # === Arguments
27
+
28
+ # * +barcode_id+ - Nominally a String, but can be anything that
29
+ # BarcodeId::coerce will accept.
30
+ # * +service_type+ - Nominally a String, but can be anything that
31
+ # ServiceType::coerce will accept.
32
+ # * +mailer_id+ - Nominally a String, but can be anything that
33
+ # MailerId::coerce will accept.
34
+ # * +serial_number+ - Nominally a String, but can be anything that
35
+ # SerialNumber::coerce will accept.
36
+ # * +routing_code+ - Nominally a String, but can be anything that
37
+ # RoutingCode::coerce will accept.
38
+
13
39
  def initialize(barcode_id,
14
40
  service_type,
15
41
  mailer_id,
@@ -22,15 +48,26 @@ module Imb
22
48
  @routing_code = RoutingCode.coerce(routing_code)
23
49
  validate_components
24
50
  end
25
-
51
+
52
+ # Return a string that represents the barcode. Each character of
53
+ # the string will be one of:
54
+ # * 'T' for a tracking mark (neither ascender nor descender)
55
+ # * 'A' for an ascender mark
56
+ # * 'D' for a descender mark
57
+ # * 'F' for a full mark (both ascender and descender)
58
+ # Print the barcode using this string and one of the USPS
59
+ # Intelligent Mail Barcode fonts
60
+
26
61
  def barcode_letters
27
62
  barcode.map { |bar| "TDAF"[bar..bar] }.join
28
63
  end
29
64
 
30
65
  private
31
66
 
67
+ # :stopdoc:
32
68
  BAR_MAP = BarMap.new
33
69
  CODEWORD_MAP = CodewordMap.new
70
+ # :startdoc:
34
71
 
35
72
  def validate_components
36
73
  components.each do |component|
@@ -1,7 +1,20 @@
1
1
  module Imb
2
2
 
3
+ # This class represents a Barcode ID
4
+
3
5
  class BarcodeId
4
6
 
7
+ # The allowable range of a barcode ID
8
+ RANGE = 0..94
9
+
10
+ # The allowable range of a barcode ID's least significant digit
11
+ LSD_RANGE = 0..4
12
+
13
+ # Turn the argument into a BarcodeID if possible. Accepts:
14
+ # * BarcodeId
15
+ # * String
16
+ # * Integer
17
+
5
18
  def self.coerce(o)
6
19
  case o
7
20
  when BarcodeId
@@ -15,32 +28,36 @@ module Imb
15
28
  end
16
29
  end
17
30
 
31
+ # Create a new BarcodeId
32
+ # * +value+ - The integer value of the barcode ID
33
+
18
34
  def initialize(value)
19
35
  @value = value
20
36
  end
21
37
 
38
+ # Validate the value. Raises ArgumentError if out of range.
39
+ # * +long_mailer_id+ - truthy if the mailer ID is long (9 digits).
40
+
22
41
  def validate(long_mailer_id)
23
42
  unless RANGE === @value
24
43
  raise ArgumentError, "Must be #{RANGE}"
25
44
  end
26
- unless LSB_RANGE === least_significant_digit
27
- raise ArgumentError, "Least significant digit must be #{LSB_RANGE}"
45
+ unless LSD_RANGE === least_significant_digit
46
+ raise ArgumentError, "Least significant digit must be #{LSD_RANGE}"
28
47
  end
29
48
  end
30
49
 
50
+ # Return true if +o+ is equal. +o+ may be any object which ::coerce
51
+ # can turn into a BarcodeId.
52
+
31
53
  def ==(o)
32
54
  BarcodeId.coerce(o).to_i == to_i
33
55
  rescue ArgumentError
34
56
  false
35
57
  end
36
58
 
37
- def most_significant_digit
38
- @value / 10
39
- end
40
-
41
- def least_significant_digit
42
- @value % 10
43
- end
59
+ # Add this object's value to target, shifting it left as many
60
+ # digts as are needed to make room.
44
61
 
45
62
  def shift_and_add_to(target, long_mailer_id)
46
63
  target *= 10
@@ -50,7 +67,7 @@ module Imb
50
67
  target
51
68
  end
52
69
 
53
- protected
70
+ # Return the integer value of the barcode ID
54
71
 
55
72
  def to_i
56
73
  @value
@@ -58,8 +75,13 @@ module Imb
58
75
 
59
76
  private
60
77
 
61
- RANGE = 0..94
62
- LSB_RANGE = 0..4
78
+ def most_significant_digit
79
+ @value / 10
80
+ end
81
+
82
+ def least_significant_digit
83
+ @value % 10
84
+ end
63
85
 
64
86
  end
65
87
 
@@ -1,7 +1,23 @@
1
1
  module Imb
2
2
 
3
+ # This class represents a mailer ID.
4
+
3
5
  class MailerId
4
6
 
7
+ # The allowable range for a short (6-digit) mailer ID
8
+ SHORT_RANGE = 0..899_999
9
+
10
+ # The allowable range for a long (9-digit) mailer ID
11
+ LONG_RANGE = 900_000_000..999_999_999
12
+
13
+ # The list of all allowable ranges for a mailer ID
14
+ RANGES = [SHORT_RANGE, LONG_RANGE]
15
+
16
+ # Turn the argument into a MailerID if possible. Accepts:
17
+ # * MailerId
18
+ # * String
19
+ # * Integer
20
+
5
21
  def self.coerce(o)
6
22
  case o
7
23
  when MailerId
@@ -15,31 +31,45 @@ module Imb
15
31
  end
16
32
  end
17
33
 
34
+ # Create a new MailerId.
35
+ # * +value+ - The integer value of the MailerId
36
+
18
37
  def initialize(value)
19
38
  @value = value
20
39
  end
21
40
 
41
+ # Validate the value. Raises ArgumentError if out of range.
42
+ # * +long_mailer_id+ - truthy if the mailer ID is long (9 digits).
43
+
22
44
  def validate(long_mailer_id)
23
45
  unless in_range?
24
46
  raise ArgumentError, "Must be #{RANGES.join(' or ')}"
25
47
  end
26
48
  end
27
49
 
50
+ # Return true if +o+ is equal. +o+ may be any object which ::coerce
51
+ # can turn into a MailerId.
52
+
28
53
  def ==(o)
29
54
  MailerId.coerce(o).to_i == to_i
30
55
  rescue ArgumentError
31
56
  false
32
57
  end
33
58
 
59
+ # Return true if this is a long (9 digit) mailer ID
60
+
34
61
  def long?
35
62
  LONG_RANGE === @value
36
63
  end
37
64
 
65
+ # Add this object's value to target, shifting it left as many
66
+ # digts as are needed to make room.
67
+
38
68
  def shift_and_add_to(target, long_mailer_id)
39
69
  target * 10 ** num_digits + to_i
40
70
  end
41
71
 
42
- protected
72
+ # Return the integer value of the mailer ID
43
73
 
44
74
  def to_i
45
75
  @value
@@ -47,10 +77,6 @@ module Imb
47
77
 
48
78
  private
49
79
 
50
- SHORT_RANGE = 0..899_999
51
- LONG_RANGE = 900_000_000..999_999_999
52
- RANGES = [SHORT_RANGE, LONG_RANGE]
53
-
54
80
  def in_range?
55
81
  RANGES.any? do |range|
56
82
  range === @value
@@ -2,6 +2,16 @@ module Imb
2
2
 
3
3
  class RoutingCode
4
4
 
5
+ # Turn the argument into a RoutingCode if possible. Accepts:
6
+ # * RoutingCode
7
+ # * nil (no routing code)
8
+ # * String of length:
9
+ # * 0 - no routing code
10
+ # * 5 - zip
11
+ # * 9 - zip + plus4
12
+ # * 11 - zip + plus4 + delivery point
13
+ # * Array of [zip, plus4, delivery point]
14
+
5
15
  def self.coerce(o)
6
16
  case o
7
17
  when nil
@@ -17,6 +27,15 @@ module Imb
17
27
  end
18
28
  end
19
29
 
30
+ # Convert a string representation of a routing code into
31
+ # an array that can be passed to the constructor.
32
+ # +s+ is a string of length:
33
+ # * 0 - no routing code
34
+ # * 5 - zip
35
+ # * 9 - zip + plus4
36
+ # * 11 - zip + plus4 + delivery point
37
+ # The result is an array of [zip, zip4, delivery point]
38
+
20
39
  def self.string_to_array(s)
21
40
  s = s.gsub(/[\D]/, '')
22
41
  match = /^(?:(\d{5})(?:(\d{4})(\d{2})?)?)?$/.match(s)
@@ -27,32 +46,34 @@ module Imb
27
46
  [zip, plus4, delivery_point]
28
47
  end
29
48
 
30
- attr_accessor :zip, :plus4, :delivery_point
49
+ # Return the ZIP (or nil)
50
+ attr_accessor :zip
51
+
52
+ # Return the plus4 (or nil)
53
+ attr_accessor :plus4
54
+
55
+ # Return the delivery point (or nil)
56
+ attr_accessor :delivery_point
31
57
 
58
+ # Create a RoutingCode. Arguments are:
59
+ # * +zip+ - Integer zip (or nil)
60
+ # * +plus4+ - Integer plus4 (or nil)
61
+ # * +delivery_point+ - Integer delivery poitn (or nil)
62
+
32
63
  def initialize(zip, plus4, delivery_point)
33
64
  @zip = arg_to_i(zip)
34
65
  @plus4 = arg_to_i(plus4)
35
66
  @delivery_point = arg_to_i(delivery_point)
36
67
  end
37
68
 
69
+ # Validate the value. Raises ArgumentError if out of range.
70
+ # * +long_mailer_id+ - truthy if the mailer ID is long (9 digits).
71
+
38
72
  def validate(long_mailer_id)
39
73
  end
40
-
41
- def convert
42
- if @zip && @plus4 && @delivery_point
43
- @zip * 1000000 + @plus4 * 100 + @delivery_point + 1000100001
44
- elsif @zip && @plus4
45
- @zip * 10000 + @plus4 + 100001
46
- elsif @zip
47
- @zip + 1
48
- else
49
- 0
50
- end
51
- end
52
74
 
53
- def to_a
54
- [@zip, @plus4, @delivery_point]
55
- end
75
+ # Return true if +o+ is equal. +o+ may be any object which ::coerce
76
+ # can turn into a RoutingCode.
56
77
 
57
78
  def ==(o)
58
79
  RoutingCode.coerce(o).to_a == to_a
@@ -60,17 +81,42 @@ module Imb
60
81
  false
61
82
  end
62
83
 
84
+ # Add this object's value to target, shifting it left as many
85
+ # digts as are needed to make room.
86
+
63
87
  def shift_and_add_to(target, long_mailer_id)
64
88
  target * 10 ** NUM_DIGITS + convert
65
89
  end
66
90
 
91
+ protected
92
+
93
+ # Convert to an array of [zip, plus4, delivery point]
94
+
95
+ def to_a
96
+ [@zip, @plus4, @delivery_point]
97
+ end
98
+
67
99
  private
68
100
 
69
- NUM_DIGITS = 11
101
+ NUM_DIGITS = 11 #:nodoc:
70
102
 
71
103
  def arg_to_i(o)
72
104
  o.andand.to_i
73
105
  end
106
+
107
+ # Convert to an integer value
108
+
109
+ def convert
110
+ if @zip && @plus4 && @delivery_point
111
+ @zip * 1000000 + @plus4 * 100 + @delivery_point + 1000100001
112
+ elsif @zip && @plus4
113
+ @zip * 10000 + @plus4 + 100001
114
+ elsif @zip
115
+ @zip + 1
116
+ else
117
+ 0
118
+ end
119
+ end
74
120
 
75
121
  end
76
122
 
@@ -1,7 +1,14 @@
1
1
  module Imb
2
2
 
3
+ # This class represents the mail piece's serial number.
4
+
3
5
  class SerialNumber
4
6
 
7
+ # Turn the argument into a SerialNumber if possible. Accepts:
8
+ # * SerialNumber
9
+ # * String
10
+ # * Integer
11
+
5
12
  def self.coerce(o)
6
13
  case o
7
14
  when SerialNumber
@@ -15,10 +22,15 @@ module Imb
15
22
  end
16
23
  end
17
24
 
25
+ # Create a new serial number from an integer.
26
+
18
27
  def initialize(value)
19
28
  @value = value
20
29
  end
21
30
 
31
+ # Validate the value. Raises ArgumentError if out of range.
32
+ # * +long_mailer_id+ - truthy if the mailer ID is long (9 digits).
33
+
22
34
  def validate(long_mailer_id)
23
35
  range = 0..max_value(long_mailer_id)
24
36
  unless range === @value
@@ -26,17 +38,23 @@ module Imb
26
38
  end
27
39
  end
28
40
 
41
+ # Return true if +o+ is equal. +o+ may be any object which ::coerce
42
+ # can turn into a SerialNumber.
43
+
29
44
  def ==(o)
30
45
  SerialNumber.coerce(o).to_i == to_i
31
46
  rescue ArgumentError
32
47
  false
33
48
  end
34
49
 
50
+ # Add this object's value to target, shifting it left as many
51
+ # digts as are needed to make room.
52
+
35
53
  def shift_and_add_to(target, long_mailer_id)
36
54
  target * 10 ** num_digits(long_mailer_id) + to_i
37
55
  end
38
56
 
39
- protected
57
+ # Return the integer value of the serial number
40
58
 
41
59
  def to_i
42
60
  @value
@@ -2,6 +2,14 @@ module Imb
2
2
 
3
3
  class ServiceType
4
4
 
5
+ # The valid range of a service type
6
+ RANGE = 0..999
7
+
8
+ # Turn the argument into a ServiceType if possible. Accepts:
9
+ # * ServiceType
10
+ # * String
11
+ # * Integer
12
+
5
13
  def self.coerce(o)
6
14
  case o
7
15
  when ServiceType
@@ -15,27 +23,38 @@ module Imb
15
23
  end
16
24
  end
17
25
 
26
+ # Create a service type from an integer
27
+
18
28
  def initialize(value)
19
29
  @value = value
20
30
  end
21
31
 
32
+ # Validate the value. Raises ArgumentError if out of range.
33
+ # * +long_mailer_id+ - truthy if the mailer ID is long (9 digits).
34
+
22
35
  def validate(long_mailer_id)
23
36
  unless (RANGE) === @value
24
37
  raise ArgumentError, "Must be #{RANGE}"
25
38
  end
26
39
  end
27
40
 
41
+ # Return true if +o+ is equal. +o+ may be any object which ::coerce
42
+ # can turn into a ServiceType.
43
+
28
44
  def ==(o)
29
45
  ServiceType.coerce(o).to_i == to_i
30
46
  rescue ArgumentError
31
47
  false
32
48
  end
33
49
 
50
+ # Add this object's value to target, shifting it left as many
51
+ # digts as are needed to make room.
52
+
34
53
  def shift_and_add_to(target, long_mailer_id)
35
54
  target * 10 ** NUM_DIGITS + to_i
36
55
  end
37
56
 
38
- protected
57
+ # Return the integer value of the service type
39
58
 
40
59
  def to_i
41
60
  @value
@@ -43,8 +62,7 @@ module Imb
43
62
 
44
63
  private
45
64
 
46
- RANGE = 0..999
47
- NUM_DIGITS = 3
65
+ NUM_DIGITS = 3 #:nodoc:
48
66
 
49
67
  end
50
68
 
@@ -51,18 +51,6 @@ module Imb
51
51
  specify {o1.should_not == o4}
52
52
  end
53
53
 
54
- describe '#most_significant_digit' do
55
- specify do
56
- BarcodeId.new(12).most_significant_digit.should == 1
57
- end
58
- end
59
-
60
- describe '#least_significant_digit' do
61
- specify do
62
- BarcodeId.new(12).least_significant_digit.should == 2
63
- end
64
- end
65
-
66
54
  describe '#validate' do
67
55
 
68
56
  let(:long_mailer_id?) {mock 'long_mailer_id?'}
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: USPS-intelligent-barcode
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
9
8
  - 2
10
- version: 0.1.2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Wayne Conrad
@@ -85,12 +85,12 @@ extensions: []
85
85
 
86
86
  extra_rdoc_files:
87
87
  - LICENSE.md
88
- - README.md
88
+ - README.rdoc
89
89
  files:
90
90
  - Gemfile
91
91
  - Gemfile.lock
92
92
  - LICENSE.md
93
- - README.md
93
+ - README.rdoc
94
94
  - Rakefile
95
95
  - USPS-intelligent-barcode.gemspec
96
96
  - VERSION