address_composer 0.1.0.pre

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.
@@ -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: []