address_composer 0.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d6f656354ec1218f98a8ca158e256e85604d2f6c
4
+ data.tar.gz: 05dcc817afac458044b712e0be501d8527f9dfd4
5
+ SHA512:
6
+ metadata.gz: 65ac54beedee44c935cf8338d7bfca27b4262b9dcd7977f1dd7c149d46b16aa0d147a71f271f104c0181b441fd5364e74b74b49454ee3d4035ba1cf0efcd61c9
7
+ data.tar.gz: 95810eb3fc9c6d867ec252d1616a1c7a28b8d8ecb56d54bf58270c1129b6bda6619edddd93901f2e1dcc0ebbb642823d371ec5d062f4ae309d75bad9dce38fa3
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
@@ -0,0 +1,3 @@
1
+ [submodule "address-formatting"]
2
+ path = address-formatting
3
+ url = git@github.com:OpenCageData/address-formatting.git
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,286 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4.5
3
+ Exclude:
4
+ - "vendor/**/*"
5
+ - "db/schema.rb"
6
+ UseCache: false
7
+ Rails:
8
+ Enabled: false
9
+ Rails/UnknownEnv:
10
+ Environments:
11
+ - beta
12
+ - development
13
+ - ephemeral
14
+ - production
15
+ - qa
16
+ - sandbox
17
+ - simulator
18
+ - test
19
+ Style/DateTime:
20
+ Enabled: true
21
+ Style/AsciiComments:
22
+ Enabled: false
23
+ Style/CollectionMethods:
24
+ Description: Preferred collection methods.
25
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#map-find-select-reduce-size
26
+ Enabled: true
27
+ PreferredMethods:
28
+ collect: map
29
+ collect!: map!
30
+ find: detect
31
+ find_all: select
32
+ reduce: inject
33
+ Style/FormatStringToken:
34
+ Description: Format string tokens
35
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#named-format-tokens
36
+ Enabled: false
37
+ Layout/DotPosition:
38
+ Description: Checks the position of the dot in multi-line method calls.
39
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains
40
+ Enabled: true
41
+ EnforcedStyle: trailing
42
+ SupportedStyles:
43
+ - leading
44
+ - trailing
45
+ Naming/FileName:
46
+ Description: Use snake_case for source file names.
47
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#snake-case-files
48
+ Enabled: false
49
+ Exclude: []
50
+ Style/GuardClause:
51
+ Description: Check for conditionals that can be replaced with guard clauses
52
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
53
+ Enabled: false
54
+ MinBodyLength: 1
55
+ Style/IfUnlessModifier:
56
+ Description: Favor modifier if/unless usage when you have a single-line body.
57
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier
58
+ Enabled: false
59
+ Style/OptionHash:
60
+ Description: Don't use option hashes when you can use keyword arguments.
61
+ Enabled: false
62
+ Style/PercentLiteralDelimiters:
63
+ Description: Use `%`-literal delimiters consistently
64
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-literal-braces
65
+ Enabled: true
66
+ Naming/PredicateName:
67
+ Description: Check the names of predicate methods.
68
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark
69
+ Enabled: true
70
+ NamePrefix:
71
+ - is_
72
+ - has_
73
+ - have_
74
+ NamePrefixBlacklist:
75
+ - is_
76
+ Exclude:
77
+ - spec/**/*
78
+ Naming/UncommunicativeMethodParamName:
79
+ # Parameter names may be equal to or greater than this value
80
+ MinNameLength: 3
81
+ AllowNamesEndingInNumbers: true
82
+ # Whitelisted names that will not register an offense
83
+ AllowedNames:
84
+ - io
85
+ - id
86
+ - to
87
+ - by
88
+ - 'on'
89
+ - in
90
+ - at
91
+ - ip
92
+ - '_'
93
+ # Blacklisted names that will register an offense
94
+ ForbiddenNames: []
95
+ Style/RaiseArgs:
96
+ Description: Checks the arguments passed to raise/fail.
97
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#exception-class-messages
98
+ Enabled: false
99
+ EnforcedStyle: exploded
100
+ SupportedStyles:
101
+ - compact
102
+ - exploded
103
+ Style/SignalException:
104
+ Description: Checks for proper usage of fail and raise.
105
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#fail-method
106
+ Enabled: false
107
+ EnforcedStyle: semantic
108
+ SupportedStyles:
109
+ - only_raise
110
+ - only_fail
111
+ - semantic
112
+ Style/SingleLineBlockParams:
113
+ Description: Enforces the names of some block params.
114
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#reduce-blocks
115
+ Enabled: false
116
+ Methods:
117
+ - reduce:
118
+ - a
119
+ - e
120
+ - inject:
121
+ - a
122
+ - e
123
+ Style/SingleLineMethods:
124
+ Description: Avoid single-line methods.
125
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-single-line-methods
126
+ Enabled: false
127
+ AllowIfMethodIsEmpty: true
128
+ Style/StringLiterals:
129
+ Description: Checks if uses of quotes match the configured preference.
130
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-string-literals
131
+ Enabled: true
132
+ EnforcedStyle: double_quotes
133
+ SupportedStyles:
134
+ - single_quotes
135
+ - double_quotes
136
+ Style/StringLiteralsInInterpolation:
137
+ Description: Checks if uses of quotes inside expressions in interpolated strings
138
+ match the configured preference.
139
+ Enabled: true
140
+ EnforcedStyle: single_quotes
141
+ SupportedStyles:
142
+ - single_quotes
143
+ - double_quotes
144
+ Metrics/BlockLength:
145
+ Enabled: false
146
+ Metrics/AbcSize:
147
+ Description: A calculated magnitude based on number of assignments, branches, and
148
+ conditions.
149
+ Enabled: false
150
+ Max: 15
151
+ Metrics/ClassLength:
152
+ Description: Avoid classes longer than 100 lines of code.
153
+ Enabled: false
154
+ CountComments: false
155
+ Max: 100
156
+ Metrics/LineLength:
157
+ Max: 100
158
+ # To make it possible to copy or click on URIs in the code, we allow lines
159
+ # containing a URI to be longer than Max.
160
+ AllowHeredoc: true
161
+ AllowURI: true
162
+ URISchemes:
163
+ - http
164
+ - https
165
+ Metrics/ModuleLength:
166
+ CountComments: false
167
+ Max: 100
168
+ Description: Avoid modules longer than 100 lines of code.
169
+ Enabled: false
170
+ Metrics/CyclomaticComplexity:
171
+ Description: A complexity metric that is strongly correlated to the number of test
172
+ cases needed to validate a method.
173
+ Enabled: false
174
+ Max: 6
175
+ Metrics/MethodLength:
176
+ Description: Avoid methods longer than 10 lines of code.
177
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#short-methods
178
+ Enabled: false
179
+ CountComments: false
180
+ Max: 10
181
+ Metrics/ParameterLists:
182
+ Description: Avoid parameter lists longer than three or four parameters.
183
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#too-many-params
184
+ Enabled: false
185
+ Max: 5
186
+ CountKeywordArgs: true
187
+ Metrics/PerceivedComplexity:
188
+ Description: A complexity metric geared towards measuring complexity for a human
189
+ reader.
190
+ Enabled: false
191
+ Max: 7
192
+ Lint/AssignmentInCondition:
193
+ Description: Don't use assignment in conditions.
194
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition
195
+ Enabled: false
196
+ AllowSafeAssignment: true
197
+ Style/InlineComment:
198
+ Description: Avoid inline comments.
199
+ Enabled: false
200
+ Naming/AccessorMethodName:
201
+ Description: Check the naming of accessor methods for get_/set_.
202
+ Enabled: false
203
+ Style/Alias:
204
+ Description: Use alias_method instead of alias.
205
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#alias-method
206
+ Enabled: false
207
+ Style/Documentation:
208
+ Description: Document classes and non-namespace modules.
209
+ Enabled: false
210
+ Style/DoubleNegation:
211
+ Description: Checks for uses of double negation (!!).
212
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-bang-bang
213
+ Enabled: false
214
+ Style/EachWithObject:
215
+ Description: Prefer `each_with_object` over `inject` or `reduce`.
216
+ Enabled: false
217
+ Style/EmptyLiteral:
218
+ Description: Prefer literals to Array.new/Hash.new/String.new.
219
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#literal-array-hash
220
+ Enabled: false
221
+ Style/ModuleFunction:
222
+ Description: Checks for usage of `extend self` in modules.
223
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#module-function
224
+ Enabled: false
225
+ Style/OneLineConditional:
226
+ Description: Favor the ternary operator(?:) over if/then/else/end constructs.
227
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#ternary-operator
228
+ Enabled: false
229
+ Style/PerlBackrefs:
230
+ Description: Avoid Perl-style regex back references.
231
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers
232
+ Enabled: false
233
+ Style/SymbolArray:
234
+ SupportedStyles:
235
+ - percent
236
+ - brackets
237
+ EnforcedStyle: percent
238
+ Style/Send:
239
+ Description: Prefer `Object#__send__` or `Object#public_send` to `send`, as `send`
240
+ may overlap with existing methods.
241
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#prefer-public-send
242
+ Enabled: false
243
+ Style/SpecialGlobalVars:
244
+ Description: Avoid Perl-style global variables.
245
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms
246
+ Enabled: false
247
+ Style/VariableInterpolation:
248
+ Description: Don't interpolate global, instance and class variables directly in
249
+ strings.
250
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#curlies-interpolate
251
+ Enabled: false
252
+ Style/WhenThen:
253
+ Description: Use when x then ... for one-line cases.
254
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#one-line-cases
255
+ Enabled: false
256
+ Lint/EachWithObjectArgument:
257
+ Description: Check for immutable argument given to each_with_object.
258
+ Enabled: true
259
+ Lint/HandleExceptions:
260
+ Description: Don't suppress exception.
261
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions
262
+ Enabled: false
263
+ Lint/LiteralInInterpolation:
264
+ Description: Checks for literals used in interpolation.
265
+ Enabled: false
266
+ Lint/LiteralAsCondition:
267
+ Description: Checks of literals used in conditions.
268
+ Enabled: false
269
+ Style/Lambda:
270
+ Description: Use the new lambda literal syntax for single-line blocks.
271
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#lambda-multi-line
272
+ Enabled: false
273
+ Rails/HttpPositionalArguments:
274
+ Enabled: false
275
+ Rails/SkipsModelValidations:
276
+ Enabled: false
277
+ Lint/AmbiguousBlockAssociation:
278
+ Enabled: false
279
+ Style/ClassAndModuleChildren:
280
+ Enabled: false
281
+ Style/RescueStandardError:
282
+ EnforcedStyle: implicit
283
+ Style/LambdaCall:
284
+ Enabled: false
285
+ Style/FrozenStringLiteralComment:
286
+ Enabled: false
@@ -0,0 +1 @@
1
+ 2.4.5
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.5
7
+ before_install: gem install bundler -v 1.17.2
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in address_composer.gemspec
6
+ gemspec
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ address_composer (0.1.0)
5
+ mustache (~> 1.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ byebug (11.1.3)
11
+ coderay (1.1.2)
12
+ diff-lcs (1.3)
13
+ method_source (1.0.0)
14
+ mustache (1.1.1)
15
+ pry (0.13.1)
16
+ coderay (~> 1.1)
17
+ method_source (~> 1.0)
18
+ pry-byebug (3.9.0)
19
+ byebug (~> 11.0)
20
+ pry (~> 0.13.0)
21
+ rake (10.5.0)
22
+ rspec (3.9.0)
23
+ rspec-core (~> 3.9.0)
24
+ rspec-expectations (~> 3.9.0)
25
+ rspec-mocks (~> 3.9.0)
26
+ rspec-core (3.9.1)
27
+ rspec-support (~> 3.9.1)
28
+ rspec-expectations (3.9.1)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.9.0)
31
+ rspec-mocks (3.9.1)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.9.0)
34
+ rspec-support (3.9.2)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ address_composer!
41
+ bundler (~> 1.17)
42
+ pry (~> 0.13)
43
+ pry-byebug (~> 3.9)
44
+ rake (~> 10.0)
45
+ rspec (~> 3.0)
46
+
47
+ BUNDLED WITH
48
+ 1.17.3
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Alejandro Arrufat Jiménez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,66 @@
1
+ # Ruby AddressComposer
2
+
3
+ Based on an amazing work of [OpenCage Data](https://github.com/OpenCageData/address-formatting/)
4
+ who collected so many international formats of postal addresses, this is a Ruby implementation
5
+ of that formatter.
6
+
7
+ The goal of this gem is processing the output of [ruby_postal](https://github.com/openvenues/ruby_postal)
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'address_composer'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install address_composer
24
+
25
+ ## Usage
26
+
27
+ ```ruby
28
+ require "address_composer"
29
+
30
+ address_components = {
31
+ "house_number" => 301,
32
+ "road" => "Hamilton Avenue",
33
+ "neighbourhood" => "Crescent Park",
34
+ "city" => "Palo Alto",
35
+ "postcode" => 94303,
36
+ "county" => "Santa Clara County",
37
+ "state" => "California",
38
+ "country" => "United States of America",
39
+ "country_code" => "US"
40
+ }
41
+
42
+ puts AddressComposer.compose(address_components)
43
+
44
+ 301 Hamilton Avenue
45
+ Palo Alto, CA 94303
46
+ United States of America
47
+ ```
48
+
49
+ ## Development
50
+
51
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
52
+
53
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
54
+
55
+ ## Contributing
56
+
57
+ Bug reports and pull requests are welcome on GitHub at https://github.com/mirubiri@gmail.com/address_composer.
58
+
59
+
60
+
61
+ Many thanks to these implementations:
62
+
63
+ - [Perl](https://github.com/OpenCageData/perl-Geo-Address-Formatter)
64
+ - [PHP](https://github.com/predicthq/address-formatter-php)
65
+ - [Javascript](https://github.com/fragaria/address-formatter)
66
+ - [Rust](https://github.com/CanalTP/address-formatter-rs)
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,36 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "address_composer/version"
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "address_composer"
7
+ gem.version = AddressComposer::VERSION
8
+ gem.authors = ["Alejandro Arrufat"]
9
+ gem.email = ["mirubiri@gmail.com"]
10
+
11
+ gem.summary = "Universal international address composer in Ruby"
12
+ gem.description = "Address Formater formats address components using coutry's formatting templates"
13
+ gem.homepage = "https://github.com/mirubiri/address_composer"
14
+ gem.license = "MIT"
15
+ gem.metadata = {
16
+ "changelog_uri" => "https://github.com/mirubiri/address_composer/CHANGELOG.md",
17
+ "documentation_uri" => "https://github.com/mirubiri/address_composer/README.md",
18
+ "homepage_uri" => "https://github.com/mirubiri/address_composer",
19
+ "source_code_uri" => "https://github.com/mirubiri/address_composer"
20
+ }
21
+
22
+ gem.files = Dir.chdir(File.expand_path(__dir__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
24
+ end
25
+
26
+ gem.required_ruby_version = ">= 2.4"
27
+ gem.require_paths = ["lib"]
28
+
29
+ gem.add_runtime_dependency "mustache", "~> 1.1"
30
+
31
+ gem.add_development_dependency "bundler", "~> 1.17"
32
+ gem.add_development_dependency "pry", "~> 0.13"
33
+ gem.add_development_dependency "pry-byebug", "~> 3.9"
34
+ gem.add_development_dependency "rake", "~> 10.0"
35
+ gem.add_development_dependency "rspec", "~> 3.0"
36
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "address_composer"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ require "pry"
10
+ Pry.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,219 @@
1
+ require "address_composer/version"
2
+ require "YAML"
3
+ require "mustache"
4
+
5
+ class AddressComposer
6
+ Templates = YAML.load_file(File.join("address-formatting/conf/countries/worldwide.yaml"))
7
+ ComponentsList = Psych.load_stream(File.read("address-formatting/conf/components.yaml"))
8
+ AllComponents = ComponentsList.map { |h| h["name"] } + ComponentsList.flat_map { |h| h["aliases"] }.compact
9
+ StateCodes = YAML.load_file(File.join("address-formatting/conf/state_codes.yaml"))
10
+ CountyCodes = YAML.load_file(File.open("address-formatting/conf/county_codes.yaml"))
11
+
12
+ class Template < Mustache
13
+ def first
14
+ lambda do |template|
15
+ render(template.strip).split("||").map(&:strip).reject(&:empty?).first
16
+ end
17
+ end
18
+ end
19
+
20
+ def self.compose(components)
21
+ new(components).compose
22
+ end
23
+
24
+ attr_accessor :components
25
+
26
+ def initialize(components)
27
+ self.components = components
28
+ end
29
+
30
+ def compose
31
+ normalize_components
32
+
33
+ if components["country_code"]
34
+ result = Template.render(template, components).squeeze("\n").lstrip.gsub(/\s*\n\s*/, "\n")
35
+ result = post_format_replace(result)
36
+ else
37
+ result = components.values.join(" ")
38
+ end
39
+
40
+ # Remove duplicated spaces
41
+ result = result.squeeze(" ")
42
+
43
+ # Remove duplicated returns and add one at the end
44
+ result = result.split("\n").uniq.join("\n") + "\n"
45
+
46
+ # Remove spaces and commas before and after return
47
+ result = result.gsub(/[,|\s]*\n[\s|,]*/, "\n")
48
+
49
+ # Remove duplicated consecutive words
50
+ result = result.gsub(/([[:alnum:]]+,)\s+\1/, '\1') # remove duplicates
51
+
52
+ # Remove trailing non-word characters
53
+ result.sub(/^[,|\s|-]*/, "")
54
+ end
55
+
56
+ private
57
+
58
+ def template
59
+ @template ||= if (components.keys & %w[road postcode]).empty?
60
+ formatting_rule["fallback_template"] || Templates["default"]["fallback_template"]
61
+ else
62
+ formatting_rule["address_template"]
63
+ end
64
+ end
65
+
66
+ def formatting_rule
67
+ formatting_rules.last
68
+ end
69
+
70
+ def country_code
71
+ @country_code || components["country_code"]
72
+ end
73
+
74
+ def formatting_rules
75
+ return @formatting_rules if @formatting_rules
76
+
77
+ initial_rule = Templates[country_code]
78
+
79
+ if initial_rule
80
+ fallback_rule = Templates[initial_rule["use_country"]]
81
+ else
82
+ initial_rule = Templates["default"]
83
+ end
84
+
85
+ @formatting_rules = [initial_rule, fallback_rule].compact
86
+ end
87
+
88
+ def normalize_components
89
+ components.transform_values!(&:to_s)
90
+ components["country_code"] = components["country_code"].to_s.upcase
91
+
92
+ fix_countries
93
+ fix_states
94
+ apply_formatting_rules
95
+ apply_aliases
96
+ normalize_aliases
97
+ end
98
+
99
+ def fix_countries
100
+ if components["country_code"] == "NL" && components["state"]
101
+ if components["state"] == "Curaçao"
102
+ components["country_code"] = "CW"
103
+ components["country"] = "Curaçao"
104
+ elsif components["state"].match?(/sint maarten/i)
105
+ components["country_code"] = "SX"
106
+ components["country"] = "Sint Maarten"
107
+ elsif components["state"].match?(/aruba/i)
108
+ components["country_code"] = "AW"
109
+ components["country"] = "Aruba"
110
+ end
111
+ end
112
+ end
113
+
114
+ def fix_states
115
+ if components["state"]&.match?(/^washington,? d\.?c\.?/i)
116
+ components["state_code"] = "DC"
117
+ components["state"] = "District of Columbia"
118
+ components["city"] = "Washington"
119
+ end
120
+ end
121
+
122
+ def apply_formatting_rules
123
+ formatting_rules.each do |rule|
124
+ new_component = rule["add_component"]
125
+ use_country = rule["use_country"]
126
+ change_country = rule["change_country"]
127
+ replaces = rule["replace"]
128
+
129
+ if use_country
130
+ @use_country = use_country
131
+ components["country_code"] = @use_country
132
+ end
133
+
134
+ if change_country
135
+ components["country"] = change_country.gsub(/\$state/, components["state"].to_s)
136
+ end
137
+
138
+ if replaces
139
+ replace(replaces)
140
+ end
141
+
142
+ if new_component
143
+ components.store(*new_component.split("="))
144
+ end
145
+ end
146
+ end
147
+
148
+ def apply_aliases
149
+ components.keys.each do |key|
150
+ component = ComponentsList.detect { |member| member["aliases"].to_a.include?(key) }
151
+ components[component["name"]] ||= components[key] if component
152
+ end
153
+
154
+ unknown_components = components.keys - AllComponents
155
+
156
+ components["attention"] = unknown_components.map do |unknown|
157
+ components[unknown]
158
+ end.join(" ")
159
+ end
160
+
161
+ def normalize_aliases
162
+ state_group = [components["state"], components["state_code"]].compact
163
+ state_code, state = StateCodes[@use_country || components["country_code"].upcase]&.select { |k, v| ([k, v] & state_group).any? }.to_a.flatten
164
+ components["state_code"] = state_code unless state_code.nil?
165
+ components["state"] = state unless state.nil?
166
+
167
+ county_group = [components["county"], components["county_code"]].compact
168
+ county_code, county = CountyCodes[components["country_code"].upcase]&.select { |k, v| ([k, v] & county_group).any? }.to_a.flatten
169
+ components["county"] = county unless county.nil?
170
+ components["county_code"] = county_code unless county_code.nil?
171
+
172
+ if components["postcode"]&.include?(";")
173
+ components.delete("postcode")
174
+ end
175
+
176
+ if components["postcode"]&.include?(",")
177
+ components["postcode"] = components["postcode"].split(",").first
178
+ end
179
+
180
+ # Clean values with "", nil or []
181
+ self.components = components.reject { |_, v| v.nil? || v.empty? }
182
+
183
+ # If country is a number use the state as country
184
+ if components["country"]&.match?(/[0-9]/)
185
+ components["country"] = components["state"]
186
+ end
187
+
188
+ # Remove components with URL
189
+ components.delete_if { |_, v| v.match?(URI::DEFAULT_PARSER.make_regexp) }
190
+ end
191
+
192
+ def replace(replaces)
193
+ replaces.each do |rule|
194
+ from, to = rule
195
+ to = to.tr("$", "\\") # FIX: Solo numeros $1, $2...
196
+
197
+ if from.match?(/^.*=/)
198
+ attr, value = from.split("=")
199
+ components[attr] = components[attr]&.gsub(/#{value}/, to)
200
+ else
201
+ components.keys.each do |key|
202
+ components[key] = components[key]&.gsub(Regexp.new(from), to)
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ def post_format_replace(string)
209
+ return string unless formatting_rule["postformat_replace"]
210
+
211
+ formatting_rule["postformat_replace"].each do |rule|
212
+ from = rule.first
213
+ to = rule.last.tr("$", "\\")
214
+ string = string.gsub(/#{from}/, to)
215
+ end
216
+
217
+ string
218
+ end
219
+ end
@@ -0,0 +1,3 @@
1
+ class AddressComposer
2
+ VERSION = "0.1.0.pre".freeze
3
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: address_composer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre
5
+ platform: ruby
6
+ authors:
7
+ - Alejandro Arrufat
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-04-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mustache
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.17'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.17'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.13'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.13'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.9'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ description: Address Formater formats address components using coutry's formatting
98
+ templates
99
+ email:
100
+ - mirubiri@gmail.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".gitmodules"
107
+ - ".rspec"
108
+ - ".rubocop.yml"
109
+ - ".ruby-version"
110
+ - ".travis.yml"
111
+ - Gemfile
112
+ - Gemfile.lock
113
+ - LICENSE.txt
114
+ - README.md
115
+ - Rakefile
116
+ - address_composer.gemspec
117
+ - bin/console
118
+ - bin/setup
119
+ - lib/address_composer.rb
120
+ - lib/address_composer/version.rb
121
+ homepage: https://github.com/mirubiri/address_composer
122
+ licenses:
123
+ - MIT
124
+ metadata:
125
+ changelog_uri: https://github.com/mirubiri/address_composer/CHANGELOG.md
126
+ documentation_uri: https://github.com/mirubiri/address_composer/README.md
127
+ homepage_uri: https://github.com/mirubiri/address_composer
128
+ source_code_uri: https://github.com/mirubiri/address_composer
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '2.4'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">"
141
+ - !ruby/object:Gem::Version
142
+ version: 1.3.1
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 2.6.14.3
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: Universal international address composer in Ruby
149
+ test_files: []