going_postal 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []