csv_geocoder 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 24a4af0aa83c6666e2cbdc6182e0797ddfc6766a42ea128022e3340317126dd9
4
+ data.tar.gz: cf3179775514d96ab8d6a3a8e17db8117114067aadfbc5ba1e4e478936b5bfc4
5
+ SHA512:
6
+ metadata.gz: 93fb3a781b60b4733f7fffb76f760df17d6dd784566579ef1e3961626e923bd4edd4d4a7af63484aed5e713242742cecafb181281532573525ca211917527fb1
7
+ data.tar.gz: 1b498fed39eb284e56da9197e017af9c5060cababbd2ea294f9b68edbd9ccca19e5ea383827cbba96ddcf795fa1aaf2004997e94b9933441edf35f25f9e10ae1
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2022-08-04
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in csv_geocoder.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "minitest", "~> 5.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,45 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ csv_geocoder (0.1.0)
5
+ geocoder (~> 1.8)
6
+ tty-progressbar (~> 0.18)
7
+ tty-prompt (~> 0.23)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ geocoder (1.8.0)
13
+ minitest (5.16.2)
14
+ pastel (0.8.0)
15
+ tty-color (~> 0.5)
16
+ rake (13.0.6)
17
+ strings-ansi (0.2.0)
18
+ tty-color (0.6.0)
19
+ tty-cursor (0.7.1)
20
+ tty-progressbar (0.18.2)
21
+ strings-ansi (~> 0.2)
22
+ tty-cursor (~> 0.7)
23
+ tty-screen (~> 0.8)
24
+ unicode-display_width (>= 1.6, < 3.0)
25
+ tty-prompt (0.23.1)
26
+ pastel (~> 0.8)
27
+ tty-reader (~> 0.8)
28
+ tty-reader (0.9.0)
29
+ tty-cursor (~> 0.7)
30
+ tty-screen (~> 0.8)
31
+ wisper (~> 2.0)
32
+ tty-screen (0.8.1)
33
+ unicode-display_width (2.2.0)
34
+ wisper (2.0.1)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ csv_geocoder!
41
+ minitest (~> 5.0)
42
+ rake (~> 13.0)
43
+
44
+ BUNDLED WITH
45
+ 2.3.6
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Arthur Cheek
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # CSVGeocoder
2
+
3
+ **Simple CSV geocoder CLI**
4
+
5
+ <p align="center">
6
+ <img src="https://user-images.githubusercontent.com/29695801/182960263-f41b3762-fa00-45eb-a8bf-d461916bbfcb.gif" alt="animated" />
7
+ </p>
8
+
9
+ ## Usage
10
+
11
+ Simply run
12
+
13
+ $ csvgeocode
14
+
15
+ 1. Provide a path to your CSV
16
+ 2. Choose your output path
17
+ 3. Choose your geocoding method
18
+ 4. Choose your output columns
19
+ 5. Enjoy your geocoded CSV
20
+
21
+ ## Geocoding methods
22
+
23
+ #### Lattitude & Longitude [preferred]
24
+
25
+ Just provide the CLI with your lat & lng columns
26
+
27
+ #### Address
28
+
29
+ Just provide the CLI with your address column
30
+
31
+ ## Installation
32
+
33
+ $ gem install csv_geocoder
34
+
35
+ ## Development
36
+
37
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
38
+
39
+ 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 the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
40
+
41
+ ## Contributing
42
+
43
+ Bug reports and pull requests are welcome on GitHub at https://github.com/madesuper/csv_geocoder.
44
+
45
+ ## License
46
+
47
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/test_*.rb"]
10
+ end
11
+
12
+ task default: :test
data/bin/csvgeocode ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'csv_geocoder'
3
+ puts CSVGeocoder.run
data/geocoded.csv ADDED
@@ -0,0 +1,3 @@
1
+ Name,Address line 1,Address line 2,Postal zip code,City,Region,Country,Tags,Services Tags,Products Tags,Phone number,Email,Image Src,Website,Page title,Page description,Meta title,Meta description,Lat,Lng,Mon,Tue,Wed,Thu,Fri,Sat,Sun,Custom Instagram,Custom Twitter
2
+ Apple HQ,1 Infinite Loop,,95014,Cupertino,California,United States,"Tag1, Tag2","iCare, Itunes","iPhone, iPad, iPod",0800 028 2329,hq@apple.com,https://images.unsplash.com/photo-1524046997286-863495b9638e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80,https://apple.com,,,,,,,09:00 - 17:00,09:00 - 17:00,09:00 - 17:00,09:00 - 17:00,09:00 - 17:00,,,https://instagram.com/apple,https://twitter.com/apple
3
+ Microsoft HQ,One Microsoft Way,,98052,Redmond,Washington,United States,"Tag3, Tag4",Repairs,"Windows, Surface",0344 800 2400,hq@microsoft.com,https://images.unsplash.com/photo-1570063578733-6a33b69d1439?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2374&q=80,https://microsoft.com,,,,,,,,,,,,,,,
@@ -0,0 +1,56 @@
1
+ require_relative "sources/csv"
2
+ require_relative "sources/csv_row"
3
+ require_relative "geocode_methods/retriever"
4
+ require_relative "output_path_retriever"
5
+ require_relative "output_columns_retriever"
6
+ require "tty-prompt"
7
+ require "tty-progressbar"
8
+
9
+ module CSVGeocoder
10
+ class CLI
11
+ def initialize
12
+ @prompt = TTY::Prompt.new(interrupt: :exit)
13
+ end
14
+
15
+ def run
16
+ @csv = Sources::CSV.new(@prompt).ask
17
+ puts
18
+ @prompt.say "Thanks! I now need to know where to output your CSV", color: :bold
19
+ @output_path = OutputPathRetriever.new(@prompt).ask_for_output_path
20
+ puts
21
+ @prompt.say "Great! I now need to know how you would like to geocode your CSV", color: :bold
22
+ @geocode_method = GeocodeMethods::Retriever.new(@prompt).ask_for_type(@csv)
23
+ puts
24
+ @prompt.say "Awesome! I now need to know where you would like me to put the geocoded columns", color: :bold
25
+ @output_columns = OutputColumnsRetriever.new(@prompt).ask_for_output_columns(@csv.headers)
26
+ puts
27
+ if @prompt.yes? "Start geocoding?"
28
+ puts
29
+ start_geocoding
30
+ end
31
+ end
32
+
33
+ def start_geocoding
34
+ bars = TTY::ProgressBar::Multi.new("[:bar] :percent :current/:total", style: { top: "", middle: "", bottom: ""})
35
+ geocode_progress = bars.register(":from -> :to", total: @csv.length)
36
+
37
+ CSV.open(@output_path, "wb") do |new_csv|
38
+ new_csv << @csv.headers
39
+ @csv.each.with_index do |row, row_num|
40
+
41
+ new_row = Sources::CSVRow.new(row, @geocode_method)
42
+ new_row.update_columns!(@output_columns)
43
+ new_csv << new_row.to_ary
44
+
45
+ geocode_progress.advance(
46
+ from: new_row.searching_by.to_s,
47
+ to: new_row.output_string
48
+ )
49
+ end
50
+ end
51
+
52
+ puts
53
+ @prompt.ok "Completed!"
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,17 @@
1
+ module CSVGeocoder
2
+ module GeocodeMethods
3
+ class Address
4
+ def initialize(csv_headers)
5
+ @csv_headers = csv_headers
6
+ end
7
+
8
+ def ask_for_required_headers(prompt)
9
+ @address_header = prompt.select("Please select the address header", @csv_headers, filter: true)
10
+ end
11
+
12
+ def search_string(row)
13
+ row[@address_header]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module CSVGeocoder
2
+ module GeocodeMethods
3
+ class Coordinates
4
+ def initialize(csv_headers)
5
+ @csv_headers = csv_headers
6
+ end
7
+
8
+ def ask_for_required_headers(prompt)
9
+ @lat_header = prompt.select("Please select the latitude header", @csv_headers, filter: true)
10
+ @lng_header = prompt.select("Please select the longitude header", @csv_headers, filter: true)
11
+ end
12
+
13
+ def search_string(row)
14
+ [ row[@lat_header], row[@lng_header] ]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ require_relative "address"
2
+ require_relative "coordinates"
3
+
4
+ module CSVGeocoder
5
+ module GeocodeMethods
6
+ class Retriever
7
+ GEOCODE_METHODS = {
8
+ "Latitude / Longitude": Coordinates,
9
+ "Address": Address
10
+ }
11
+
12
+ def initialize(prompt)
13
+ @prompt = prompt
14
+ end
15
+
16
+ def ask_for_type(csv)
17
+ geocode_type = @prompt.select("How are we geocoding today?", GEOCODE_METHODS.keys)
18
+ geocoder = GEOCODE_METHODS[geocode_type].new(csv.headers)
19
+ geocoder.ask_for_required_headers(@prompt)
20
+ geocoder
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ module CSVGeocoder
2
+ class GeocodeResult
3
+ def initialize(result)
4
+ @result = result
5
+ end
6
+
7
+ def address
8
+ [
9
+ "#{@result.house_number} #{@result.street}".strip,
10
+ @result.village,
11
+ @result.town
12
+ ].select{|res| res }.join(", ")
13
+ end
14
+
15
+ def city
16
+ @result.city
17
+ end
18
+
19
+ def region
20
+ @result.state || @result.county || @result.suburb || @result.neighbourhood
21
+ end
22
+
23
+ def country
24
+ @result.country
25
+ end
26
+
27
+ def postcode
28
+ @result.postal_code
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,17 @@
1
+ module CSVGeocoder
2
+ class OutputColumnsRetriever
3
+ def initialize(prompt)
4
+ @prompt = prompt
5
+ end
6
+
7
+ def ask_for_output_columns(select_options)
8
+ @prompt.collect do
9
+ key(:city_header).select("Please select the city header", select_options, filter: true)
10
+ key(:region_header).select("Please select the region header", select_options, filter: true)
11
+ key(:country_header).select("Please select the country header", select_options, filter: true)
12
+ key(:postcode_header).select("Please select the postcode header", select_options, filter: true)
13
+ key(:address_header).select("Please select the address header", select_options, filter: true)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module CSVGeocoder
2
+ class OutputPathRetriever
3
+ def initialize(prompt)
4
+ @prompt = prompt
5
+ end
6
+
7
+ def ask_for_output_path
8
+ @prompt.ask("Where do you want to save the new CSV?",
9
+ required: true,
10
+ value: "./geocoded.csv",
11
+ convert: :path
12
+ )
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ require "csv"
2
+ module CSVGeocoder
3
+ module Sources
4
+ class CSV
5
+ def initialize(prompt)
6
+ @prompt = prompt
7
+ end
8
+
9
+ def ask
10
+ csv = nil
11
+ until csv
12
+ begin
13
+ csv_path = @prompt.ask("Hi, whats the path to your CSV?", required: true)
14
+ csv ||= ::CSV.read(csv_path, headers: true)
15
+ rescue Errno::ENOENT
16
+ @prompt.error "Thats not a valid CSV path, please enter it again"
17
+ @prompt.warn "If you're on mac, right click the file, hold option, then click copy as pathname"
18
+ end
19
+ end
20
+ csv
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,43 @@
1
+ require "geocoder"
2
+ require_relative "../geocode_result"
3
+ module CSVGeocoder
4
+ module Sources
5
+ class CSVRow
6
+ def initialize(row, geocode_method)
7
+ @row = row
8
+ @geocode_method = geocode_method
9
+ end
10
+
11
+ def geocoded_result
12
+ return @geocoded_result if @geocoded_result
13
+ search_result = Geocoder.search(searching_by).first
14
+ return nil unless search_result
15
+ @geocoded_result = GeocodeResult.new(search_result)
16
+ end
17
+
18
+ def update_columns!(output_columns)
19
+ return false unless geocoded_result
20
+
21
+ @row[output_columns[:address_header]] = geocoded_result.address
22
+ @row[output_columns[:city_header]] = geocoded_result.city
23
+ @row[output_columns[:region_header]] = geocoded_result.region
24
+ @row[output_columns[:country_header]] = geocoded_result.country
25
+ @row[output_columns[:postcode_header]] = geocoded_result.postcode
26
+ true
27
+ end
28
+
29
+ def to_ary
30
+ @row.to_ary.map(&:last)
31
+ end
32
+
33
+ def output_string
34
+ return "COULDN'T GEOCODE" unless geocoded_result
35
+ "#{geocoded_result.address}"
36
+ end
37
+
38
+ def searching_by
39
+ @geocode_method.search_string(@row)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CSVGeocoder
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "csv_geocoder/version"
4
+ require_relative "csv_geocoder/cli"
5
+
6
+ module CSVGeocoder
7
+ def self.run
8
+ CLI.new.run
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ module CSVGeocoder
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: csv_geocoder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Arthur Cheek
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-08-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: tty-prompt
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.23'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.23'
27
+ - !ruby/object:Gem::Dependency
28
+ name: tty-progressbar
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.18'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.18'
41
+ - !ruby/object:Gem::Dependency
42
+ name: geocoder
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.8'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.8'
55
+ description: Write a longer description or delete this line.
56
+ email:
57
+ - artyrcheek@gmail.com
58
+ executables:
59
+ - csvgeocode
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - CHANGELOG.md
64
+ - Gemfile
65
+ - Gemfile.lock
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - bin/csvgeocode
70
+ - geocoded.csv
71
+ - lib/csv_geocoder.rb
72
+ - lib/csv_geocoder/cli.rb
73
+ - lib/csv_geocoder/geocode_methods/address.rb
74
+ - lib/csv_geocoder/geocode_methods/coordinates.rb
75
+ - lib/csv_geocoder/geocode_methods/retriever.rb
76
+ - lib/csv_geocoder/geocode_result.rb
77
+ - lib/csv_geocoder/output_columns_retriever.rb
78
+ - lib/csv_geocoder/output_path_retriever.rb
79
+ - lib/csv_geocoder/sources/csv.rb
80
+ - lib/csv_geocoder/sources/csv_row.rb
81
+ - lib/csv_geocoder/version.rb
82
+ - sig/csv_geocoder.rbs
83
+ homepage: https://arthurcheek.com
84
+ licenses:
85
+ - MIT
86
+ metadata:
87
+ homepage_uri: https://arthurcheek.com
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 2.6.0
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubygems_version: 3.3.6
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Write a short summary, because RubyGems requires one.
107
+ test_files: []