auto_location 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +37 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1 -0
- data/README.rdoc +3 -0
- data/Rakefile +34 -0
- data/auto_location.gemspec +20 -0
- data/data/cities.csv +29513 -0
- data/data/states.csv +1 -0
- data/data/zips.csv +1 -0
- data/lib/auto_location/string.rb +46 -0
- data/lib/auto_location/version.rb +3 -0
- data/lib/auto_location.rb +58 -0
- data/lib/tasks/auto_location_tasks.rake +4 -0
- data/spec/lib/auto_location_spec.rb +89 -0
- data/spec/spec_helper.rb +1 -0
- metadata +105 -0
data/data/states.csv
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
AL
|
data/data/zips.csv
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
35004
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class String
|
2
|
+
# Add methods to String class
|
3
|
+
def validated_location
|
4
|
+
# If search includes valid zipcode, return zipcode
|
5
|
+
# If zipcode doesn't exist, do city search.
|
6
|
+
# If city doesn't exist, do state search.
|
7
|
+
zipcode(self) || city_perfect_match(self) || city(self) || state(self) || AutoLocation.not_found_location
|
8
|
+
end
|
9
|
+
|
10
|
+
# Check if zipcode exists
|
11
|
+
def zipcode(zipcode)
|
12
|
+
zipcode.scan(/\d{5}/).each do |token|
|
13
|
+
result = AutoLocation.zips[token.to_i]
|
14
|
+
return { location: {zipcode: token, city: result[0], state: result[1]}, type: 'zipcode' } unless result == nil
|
15
|
+
end
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
def city_perfect_match(city)
|
20
|
+
city = city.upcase
|
21
|
+
result = AutoLocation.cities_hash[city]
|
22
|
+
result == nil ? false : { location: {city: result[0], state: result[1]}, type: 'city' }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Find a city with the search string
|
26
|
+
def city(city)
|
27
|
+
city = city.upcase
|
28
|
+
results = []
|
29
|
+
AutoLocation.cities.find_all do |row|
|
30
|
+
results << row unless city[row[0]] == nil
|
31
|
+
end
|
32
|
+
result = results == [] ? nil : results.max {|a,b| a[1].length <=> b[1].length}
|
33
|
+
result == nil ? false : { location: {city: result[1], state: result[2]}, type: 'city' }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Find a state with the search string
|
37
|
+
def state(state)
|
38
|
+
state = state.upcase
|
39
|
+
# add a white space for easier regex match
|
40
|
+
state.split(/[\s\,]/).each do |token|
|
41
|
+
found_state = AutoLocation.states[token]
|
42
|
+
return { location: found_state, type: 'state' } unless AutoLocation.states[token] == nil
|
43
|
+
end
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
if RUBY_VERSION.to_f >= 1.9
|
2
|
+
require 'csv'
|
3
|
+
else
|
4
|
+
require 'rubygems'
|
5
|
+
require 'faster_csv'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'auto_location/string'
|
9
|
+
|
10
|
+
module AutoLocation
|
11
|
+
city_file = File.open(File.join(File.dirname(__FILE__), '..', 'data', 'cities.csv'))
|
12
|
+
state_file = File.open(File.join(File.dirname(__FILE__), '..', 'data', 'states.csv'))
|
13
|
+
|
14
|
+
csv_method = lambda{ |x| RUBY_VERSION.to_f >= 1.9 ? CSV.read(x) : FasterCSV.parse(x) }
|
15
|
+
# regular expressions for city: CITY_NAME_PART1.*PART2.*....*STATE.*
|
16
|
+
# ex. San+.*Jose+.*(CA)*.*
|
17
|
+
@cities ||= csv_method.call(city_file).map do |x|
|
18
|
+
[ Regexp.new(((x[2].split(/[\s\,]/).map(&:strip) << ('(' + x[1] + ')')).join('.*') + '*.*').upcase),
|
19
|
+
x[2],
|
20
|
+
x[1]
|
21
|
+
]
|
22
|
+
end
|
23
|
+
@cities_hash ||= Hash[(csv_method.call(city_file)).map do |x|
|
24
|
+
[(x[2] + ', ' + x[1]).upcase, [x[2], x[1]]]
|
25
|
+
end]
|
26
|
+
@zips ||= Hash[(csv_method.call(city_file)).map do |x|
|
27
|
+
[x[0].to_i, [x[2], x[1]]]
|
28
|
+
end]
|
29
|
+
@states ||= Hash[(csv_method.call(state_file)).map do |x|
|
30
|
+
state = x[0]
|
31
|
+
x[0] = state.upcase
|
32
|
+
x << state
|
33
|
+
end]
|
34
|
+
# default result if zipcode, city, state search all failed
|
35
|
+
@not_found_location ||= {error: "Location Not Found"}.freeze
|
36
|
+
|
37
|
+
class << self
|
38
|
+
def cities
|
39
|
+
@cities
|
40
|
+
end
|
41
|
+
|
42
|
+
def cities_hash
|
43
|
+
@cities_hash
|
44
|
+
end
|
45
|
+
|
46
|
+
def zips
|
47
|
+
@zips
|
48
|
+
end
|
49
|
+
|
50
|
+
def states
|
51
|
+
@states
|
52
|
+
end
|
53
|
+
|
54
|
+
def not_found_location
|
55
|
+
@not_found_location
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require File.expand_path('../../../lib/auto_location.rb', __FILE__)
|
2
|
+
|
3
|
+
describe 'auto location parse location from string' do
|
4
|
+
let(:not_found_location_response) do
|
5
|
+
{error: "Location Not Found"}
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:valid_city_response) do
|
9
|
+
{location: {city: "San Jose", state: "CA"}, type: 'city'}
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:valid_zip_code_response) do
|
13
|
+
{location: {zipcode: '95129', city: "San Jose", state: "CA"}, type: 'zipcode'}
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:valid_state_response_short) do
|
17
|
+
{location: 'CA', type: 'state'}
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:valid_state_response_long) do
|
21
|
+
{location: 'California', type: 'state'}
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'get zipcode' do
|
25
|
+
it 'when input contains valid zipcode' do
|
26
|
+
expect('string'.zipcode('hello world, San Jose, CA, 95129')).to eq(valid_zip_code_response)
|
27
|
+
expect('string'.zipcode('any random 95129 test here')).to eq(valid_zip_code_response)
|
28
|
+
expect('string'.zipcode('verymessystringthatcontains95129aszipcode')).to eq(valid_zip_code_response)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'when input does not contain valid zipcode' do
|
32
|
+
expect('string'.zipcode('35000')).to be_falsey
|
33
|
+
expect('string'.zipcode('No valid zip 35000 inside string')).to be_falsey
|
34
|
+
expect('string'.zipcode('350000')).to be_falsey
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'get city' do
|
39
|
+
it 'when input contains valid city' do
|
40
|
+
expect('string'.city('1428 downtown south San Jose, San Jose, CA')).to eq(valid_city_response)
|
41
|
+
expect('string'.city('San some text Jose, some textCA')).to eq(valid_city_response)
|
42
|
+
expect('string'.city('sanjoseca')).to eq(valid_city_response)
|
43
|
+
expect('string'.city('some text San some text Jose some text')).to eq(valid_city_response)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'when input does not contain valid city' do
|
47
|
+
expect('string'.city('1428 San Josa')).to be_falsey
|
48
|
+
expect('string'.city('San Hose, CA')).to be_falsey
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'when input perfectly matches to a city' do
|
52
|
+
expect('string'.city_perfect_match('San Jose, CA')).to eq(valid_city_response)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'get state' do
|
57
|
+
it 'when input contains valid state' do
|
58
|
+
expect('string'.state('ca')).to eq(valid_state_response_short)
|
59
|
+
expect('string'.state('california')).to eq(valid_state_response_long)
|
60
|
+
expect('string'.state('some text cA')).to eq(valid_state_response_short)
|
61
|
+
expect('string'.state('some text California')).to eq(valid_state_response_long)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'when input does not contain valid state' do
|
65
|
+
expect('string'.state('cc')).to be_falsey
|
66
|
+
expect('string'.state('Calfooooo')).to be_falsey
|
67
|
+
expect('string'.state('some text cC')).to be_falsey
|
68
|
+
expect('string'.state('some text Califoooo')).to be_falsey
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'get validated location' do
|
73
|
+
it 'when input contains valid zip' do
|
74
|
+
expect('1428 downtown south San Jose, 95129, San Jose, CA'.validated_location).to eq(valid_zip_code_response)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'when input contains valid city' do
|
78
|
+
expect('1428 downtown south San Jose, 35000, San Jose, CA'.validated_location).to eq(valid_city_response)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'when input contains valid state' do
|
82
|
+
expect('1428 random text, 35000, San Josa, CA'.validated_location).to eq(valid_state_response_short)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'when input contains no valid location' do
|
86
|
+
expect('1428 random text, 35000, San Josa, CC'.validated_location).to eq(not_found_location_response)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ENV['RAILS_ENV'] = 'test'
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: auto_location
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lu Zou
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: fastercsv
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A light-weight gem, get valid US zipcode/city/states from any string.
|
56
|
+
email:
|
57
|
+
- luxizou.web@gmail.com@move.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- Gemfile
|
64
|
+
- Gemfile.lock
|
65
|
+
- MIT-LICENSE
|
66
|
+
- README.md
|
67
|
+
- README.rdoc
|
68
|
+
- Rakefile
|
69
|
+
- auto_location.gemspec
|
70
|
+
- data/cities.csv
|
71
|
+
- data/states.csv
|
72
|
+
- data/zips.csv
|
73
|
+
- lib/auto_location.rb
|
74
|
+
- lib/auto_location/string.rb
|
75
|
+
- lib/auto_location/version.rb
|
76
|
+
- lib/tasks/auto_location_tasks.rake
|
77
|
+
- spec/lib/auto_location_spec.rb
|
78
|
+
- spec/spec_helper.rb
|
79
|
+
homepage: http://github.com/luzou0526/autoLoc
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 2.5.1
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: Valid US locations from string
|
103
|
+
test_files:
|
104
|
+
- spec/lib/auto_location_spec.rb
|
105
|
+
- spec/spec_helper.rb
|