going_postal 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/README.rdoc +77 -0
  2. data/lib/going_postal.rb +220 -0
  3. metadata +51 -0
@@ -0,0 +1,77 @@
1
+ = GoingPostal
2
+
3
+ The GoingPostal mixin provides classes with postcode formatting and validation
4
+ methods.
5
+
6
+ == Installation
7
+
8
+ $ gem install going_postal
9
+
10
+ == Usage
11
+
12
+ GoingPostal can be used as a mixin:
13
+
14
+ class Address
15
+ include GoingPostal
16
+ attr_accessor :number, :street, :city, :postcode, :country_code
17
+
18
+ def initialize(number, street, :city, postcode, country_code="GB")
19
+ self.number = number
20
+ self.street = street
21
+ self.city = city
22
+ self.postcode = postcode
23
+ self.country_code = country_code
24
+ end
25
+
26
+ def postcode=(value)
27
+ @postcode = format_postcode(value)
28
+ end
29
+
30
+ def valid?
31
+ number && street && city && postcode_valid?
32
+ end
33
+ end
34
+
35
+ or as a namespaced collection of methods:
36
+
37
+ GoingPostal.postcode?("sl41eg", "GB") #=> "SL4 1EG"
38
+ GoingPostal.postcode?("200378001", "US") #=> "20037-8001"
39
+
40
+ The methods available are #postcode? for checking validity, and format_postcode
41
+ which returns a formatted postcode. Both take arguments of a string, the
42
+ postcode, and a two letter country code. If the class has a #country_code
43
+ method, the country_code argument on the provided methods becomes optional. If
44
+ the class also has one of #postcode, #post_code, #zipcode, #zip_code, or #zip,
45
+ the string argument on the provided methods becomes optional.
46
+
47
+ postcode? is aliased as post_code?, zip?, zipcode?, zip_code?, valid_postcode?,
48
+ valid_post_code?, valid_zip?, valid_zipcode?, valid_zip_code?, postcode_valid?,
49
+ post_code_valid?, zip_valid?, zipcode_valid? and zip_code_valid? The alias
50
+ valid? is also available directly on the GoingPostal module.
51
+
52
+ format_postcode is aliased as format_post_code, format_zip, format_zipcode, and
53
+ format_zip_code.
54
+
55
+ == Licence
56
+
57
+ (The MIT License)
58
+
59
+ Copyright (c) 2011 Global Personals, Ltd.
60
+
61
+ Permission is hereby granted, free of charge, to any person obtaining a copy
62
+ of this software and associated documentation files (the "Software"), to deal
63
+ in the Software without restriction, including without limitation the rights
64
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
65
+ copies of the Software, and to permit persons to whom the Software is
66
+ furnished to do so, subject to the following conditions:
67
+
68
+ The above copyright notice and this permission notice shall be included in
69
+ all copies or substantial portions of the Software.
70
+
71
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
72
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
73
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
74
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
76
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
77
+ THE SOFTWARE.
@@ -0,0 +1,220 @@
1
+ # The GoingPostal mixin provides classes with postcode formatting and validation
2
+ # methods. If the class has a #country_code method, the country_code argument on
3
+ # the provided methods becomes optional. If the class also has one of #postcode,
4
+ # #post_code, #zipcode, #zip_code, or #zip, the string argument on the provided
5
+ # methods becomes optional.
6
+ #
7
+ # class Address
8
+ # include GoingPostal
9
+ # attr_accessor :number, :street, :city, :postcode, :country_code
10
+ #
11
+ # def initialize(number, street, :city, postcode, country_code="GB")
12
+ # self.number = number
13
+ # self.street = street
14
+ # self.city = city
15
+ # self.postcode = postcode
16
+ # self.country_code = country_code
17
+ # end
18
+ #
19
+ # def postcode=(value)
20
+ # @postcode = format_postcode(value)
21
+ # end
22
+ #
23
+ # def valid?
24
+ # number && street && city && postcode_valid?
25
+ # end
26
+ # end
27
+ #
28
+ # The methods can also be called directly on the GoingPostal module.
29
+ #
30
+ # GoingPostal.postcode?("sl41eg", "GB") #=> "SL4 1EG"
31
+ # GoingPostal.postcode?("200378001", "US") #=> "20037-8001"
32
+ #
33
+ # Currently supported countries are United Kingdom (GB, UK), United States (US),
34
+ # Canada (CA), Australia (AU), New Zeland (NZ), and South Africa (ZA).
35
+ #
36
+ # Ireland (IE) is supported insomuch as, Ireland doesn't use postcodes, so "" or
37
+ # nil are considered valid.
38
+ #
39
+ # Currently unsupported countries will be formatted by simply stripping leading
40
+ # and trailing whitespace, and any input will be considered valid.
41
+ #
42
+ module GoingPostal
43
+ extend self
44
+
45
+ # :section: Validation
46
+
47
+ # :call-seq: postcode?([string[, country_code]]) -> formatted_str or false
48
+ #
49
+ # Returns a formatted postcode as a string if string is a valid postcode,
50
+ # false otherwise.
51
+ #
52
+ # If calling this method on the GoingPostal module the country_code argument
53
+ # is required and should be a two letter country code.
54
+ #
55
+ # If the GoingPostal module has been mixed in to a class, and the class has
56
+ # a #country_code method, the country_code argument is optional, defaulting
57
+ # to the value returned by #country_code. If the class also has a #postcode,
58
+ # #post_code, #zipcode, #zip_code, or #zip method, the string argument becomes
59
+ # optional.
60
+ #
61
+ # Postcodes for unknown countries will always be considered valid, the return
62
+ # value will consist of the input stripped of leading and trailing whitespace.
63
+ #
64
+ # Ireland (IE) has no postcodes, "" will be returned from in input of "" or
65
+ # nil, false otherwise.
66
+ #
67
+ def postcode?(*args)
68
+ string, country_code = get_args_for_format_postcode(args)
69
+ case country_code.to_s.upcase
70
+ when "GB", "UK", "US", "USA", "CA", "AU", "NZ", "ZA"
71
+ format_postcode(string, country_code) || false
72
+ when "IE"
73
+ string.nil? || string.to_s.empty? ? "" : false
74
+ else
75
+ format_postcode(string, country_code)
76
+ end
77
+ end
78
+ alias post_code? postcode?
79
+ alias zip? postcode?
80
+ alias zipcode? postcode?
81
+ alias zip_code? postcode?
82
+ alias valid_postcode? postcode?
83
+ alias valid_post_code? postcode?
84
+ alias valid_zip? postcode?
85
+ alias valid_zipcode? postcode?
86
+ alias valid_zip_code? postcode?
87
+ alias postcode_valid? postcode?
88
+ alias post_code_valid? postcode?
89
+ alias zip_valid? postcode?
90
+ alias zipcode_valid? postcode?
91
+ alias zip_code_valid? postcode?
92
+
93
+ # :call-seq: self.valid?([string[, country_code]]) -> formatted_string or false
94
+ #
95
+ # Alias for #postcode?
96
+ #--
97
+ # this is just here to trick rdoc, the class alias below will overwrite this
98
+ # empty method.
99
+ #++
100
+ def self.valid?; end
101
+
102
+ class << self
103
+ alias valid? postcode?
104
+ end
105
+
106
+ # :section: Formatting
107
+
108
+ # :call-seq: format_postcode([string[, country_code]]) -> formatted_str or nil
109
+ #
110
+ # Returns a formatted postcode as a string if string is a valid postcode, nil
111
+ # otherwise.
112
+ #
113
+ # If calling this method on the GoingPostal module the country_code argument
114
+ # is required and should be a two letter country code.
115
+ #
116
+ # If the GoingPostal module has been mixed in to a class, and the class has
117
+ # a #country_code method, the country_code argument is optional, defaulting
118
+ # to the value returned by #country_code. If the class also has a #postcode,
119
+ # #post_code, #zipcode, #zip_code, or #zip method, the string argument becomes
120
+ # optional.
121
+ #
122
+ # Postcodes for unknown countries will simply be stripped of leading and
123
+ # trailing whitespace.
124
+ #
125
+ # Ireland (IE) has no postcodes, so nil will always be returned.
126
+ #
127
+ def format_postcode(*args)
128
+ string, country_code = get_args_for_format_postcode(args)
129
+ case country_code.to_s.upcase
130
+ when "GB", "UK"
131
+ format_gb_postcode(string)
132
+ when "US", "USA"
133
+ format_us_zipcode(string)
134
+ when "CA"
135
+ format_ca_postcode(string)
136
+ when "AU", "NZ", "ZA"
137
+ format_au_postcode(string)
138
+ when "IE"
139
+ nil
140
+ else
141
+ string.to_s.strip
142
+ end
143
+ end
144
+ alias format_post_code format_postcode
145
+ alias format_zip format_postcode
146
+ alias format_zipcode format_postcode
147
+ alias format_zip_code format_postcode
148
+
149
+ # :stopdoc:
150
+
151
+ def format_gb_postcode(string)
152
+ out_code = string.to_s.upcase.delete(" \t\r\n")
153
+ in_code = out_code.slice!(-3, 3)
154
+ if out_code =~ /^[A-Z]{1,2}([1-9][0-9A-HJKMNPR-Y]?|0[A-HJKMNPR-Y]?)$/ &&
155
+ in_code =~ /^[0-9][A-HJLNP-Z]{2}$/
156
+ [out_code, in_code].join(" ")
157
+ end
158
+ end
159
+ alias format_uk_postcode format_gb_postcode
160
+
161
+ def format_ca_postcode(string)
162
+ forward_sort_area = string.to_s.upcase.delete(" \t\r\n")
163
+ local_delivery_unit = forward_sort_area.slice!(-3, 3)
164
+ if forward_sort_area =~ /^[A-CEGHJK-NPR-TVXY][0-9][A-CEGHJK-NPR-TV-Z]$/ &&
165
+ local_delivery_unit =~ /[0-9][A-CEGHJK-NPR-TV-Z][0-9]/
166
+ [forward_sort_area, local_delivery_unit].join(" ")
167
+ end
168
+ end
169
+
170
+ def format_au_postcode(string)
171
+ string = string.to_s.delete(" \t\r\n")
172
+ string if string =~ /^[0-9]{4}$/
173
+ end
174
+ alias format_nz_postcode format_au_postcode
175
+ alias format_za_postcode format_au_postcode
176
+
177
+ def format_us_zipcode(string)
178
+ zip = string.to_s.delete("- \t\r\n")
179
+ plus_four = zip.slice!(5, 4)
180
+ plus_four = nil if plus_four && plus_four.empty?
181
+ if zip =~ /^[0-9]{5}$/ && (plus_four.nil? || plus_four =~ /^[0-9]{4}$/)
182
+ [zip, plus_four].compact.join("-")
183
+ end
184
+ end
185
+ alias format_us_postcode format_us_zipcode
186
+
187
+ private
188
+
189
+ def get_args_for_format_postcode(args)
190
+ case args.length
191
+ when 2
192
+ args
193
+ when 0
194
+ [postcode_for_format_postcode, country_code_for_format_postcode]
195
+ when 1
196
+ args << country_code_for_format_postcode
197
+ else
198
+ message = "wrong number of arguments (#{args.length} for 0..2)"
199
+ raise ArgumentError, message, caller(2)
200
+ end
201
+ end
202
+
203
+ def country_code_for_format_postcode
204
+ if respond_to?(:country_code)
205
+ country_code
206
+ else
207
+ raise ArgumentError, "wrong number of arguments (1 for 0..2)", caller(3)
208
+ end
209
+ end
210
+
211
+ POSTCODE_ALIASES = [:postcode, :post_code, :zipcode, :zip_code, :zip]
212
+ def postcode_for_format_postcode
213
+ if ali = POSTCODE_ALIASES.find {|a| respond_to?(a)}
214
+ send(ali)
215
+ else
216
+ raise ArgumentError, "wrong number of arguments (0 for 0..2)", caller(3)
217
+ end
218
+ end
219
+
220
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: going_postal
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Matthew Sadler
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-21 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: Post/zip code formatting and validation for the UK, US, CA and more.
15
+ email: mat@sourcetagsandcodes.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files:
19
+ - README.rdoc
20
+ files:
21
+ - lib/going_postal.rb
22
+ - README.rdoc
23
+ homepage: http://github.com/globaldev/going_postal
24
+ licenses: []
25
+ post_install_message:
26
+ rdoc_options:
27
+ - --main
28
+ - README.rdoc
29
+ - --charset
30
+ - utf-8
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubyforge_project:
47
+ rubygems_version: 1.8.7
48
+ signing_key:
49
+ specification_version: 3
50
+ summary: Global post/zip code formatting and validation mixin
51
+ test_files: []