sora_geocoding 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ guard :rspec, cmd: 'bundle exec rspec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { 'spec' }
5
+ end
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2020- SORA, inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 hirontan
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.
@@ -0,0 +1,82 @@
1
+ # SoraGeocoding
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/sora_geocoding`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'sora_geocoding'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install sora_geocoding
22
+
23
+ ## Usage
24
+
25
+ ### Search
26
+
27
+ ##### No options
28
+ ```
29
+ SoraGeocoding.search('Tokyo')
30
+ => {:site=>"geocoding", :data=>"<?xml version='1.0' encoding='UTF-8'?>\n<result>\n<version>1.2</version>\n<address>Tokyo</address>\n<coordinate>\n<lat>35.676192</lat>\n<lng>139.650311</lng>\n<lat_dms>35,40,34.291</lat_dms>\n<lng_dms>139,39,1.118</lng_dms>\n</coordinate>\n<open_location_code>8Q7XMMG2+F4</open_location_code>\n<url>https://www.geocoding.jp/?q=Tokyo</url>\n<needs_to_verify>no</needs_to_verify>\n<google_maps>東京都</google_maps>\n</result>\n"}
31
+ ```
32
+
33
+ ##### Optional
34
+ - set options
35
+ - site: 'yahoo'
36
+ - yahoo_app_id: 'xxxxxxxx'
37
+ - Get the ClientId: https://developer.yahoo.co.jp/start/
38
+
39
+ ```
40
+ SoraGeocoding.search('東京都', {site: 'yahoo', yahoo_appid: 'xxxxxxxx'})
41
+ => {:site=>"yahoo", :data=>"<?xml version='1.0' encoding='UTF-8'?>\n<YDF firstResultPosition='1' totalResultsAvailable='1793198' totalResultsReturned='1' xmlns='http://olp.yahooapis.jp/ydf/1.0'><ResultInfo><Count>1</Count><Total>1793198</Total><Start>1</Start><Status>200</Status><Description/><Copyright/><Latency>0.036</Latency></ResultInfo><Feature><Id>13112</Id><Gid/><Name>東京都世田谷区</Name><Geometry><Type>point</Type><Coordinates>139.65324950,35.64657460</Coordinates><BoundingBox>139.58242700,35.59004000 139.68655700,35.68297400</BoundingBox></Geometry><Category/><Description/><Style/><Property><Uid>9b7486bd58ee135ffec334df2975f4f37690b3cf</Uid><CassetteId>b22fee69b0dcaf2c2fe2d6a27906dafc</CassetteId><Yomi>トウキョウトセタガヤク</Yomi><Country><Code>JP</Code><Name>日本</Name></Country><Address>東京都世田谷区</Address><AddressElement><Name>東京都</Name><Kana>とうきょうと</Kana><Level>prefecture</Level></AddressElement><AddressElement><Name>世田谷区</Name><Kana>せたがやく</Kana><Level>city</Level></AddressElement><GovernmentCode>13112</GovernmentCode><AddressMatchingLevel>2</AddressMatchingLevel><Approximation>0.429</Approximation><AddressType>特別区</AddressType><OpenForBusiness/><Detail><NameHiragana>とうきょうとせたがやく</NameHiragana><OldAddressFlag>false</OldAddressFlag></Detail></Property></Feature></YDF>\n<!-- xxxcache nohit 0.038, 0.001, 0.001 -->"}
42
+ ```
43
+
44
+ ### Coordinates
45
+
46
+ ##### No options
47
+ ```
48
+ SoraGeocoding.coordinates('Tokyo')
49
+ => {:site=>"geocoding", :coordinates=>{:lat=>"35.676192", :lon=>"139.650311"}}
50
+ ```
51
+
52
+ ##### Optional
53
+ - set options
54
+ - site: 'yahoo'
55
+ - yahoo_app_id: 'xxxxxxxxx'
56
+ - Get the ClientId: https://developer.yahoo.co.jp/start/
57
+
58
+ ```
59
+ SoraGeocoding.coordinates('東京都', {site: 'yahoo', yahoo_appid: 'xxxxxxxxx'})
60
+ => {:site=>"yahoo", :coordinates=>{:lat=>"35.64657460", :lon=>"139.65324950"}}
61
+ ```
62
+
63
+ ## Development
64
+
65
+ 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.
66
+
67
+ 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).
68
+
69
+ ## Contributing
70
+
71
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/sora_geocoding. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
72
+
73
+ ## License
74
+
75
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
76
+
77
+ ## Code of Conduct
78
+
79
+ Everyone interacting in the SoraGeocoding project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/sora_geocoding/blob/master/CODE_OF_CONDUCT.md).
80
+
81
+ ## Reference
82
+ - https://github.com/alexreisner/geocoder
@@ -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,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'sora_geocoding'
5
+ require 'irb'
6
+
7
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install --path ./.bundle/
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,70 @@
1
+ #
2
+ # = Hash Recursive Merge
3
+ #
4
+ # Merges a Ruby Hash recursively, Also known as deep merge.
5
+ # Recursive version of Hash#merge and Hash#merge!.
6
+ #
7
+ # Category:: Ruby
8
+ # Package:: Hash
9
+ # Author:: Simone Carletti <weppos@weppos.net>
10
+ # Copyright:: 2007-2008 The Authors
11
+ # License:: MIT License
12
+ # Link:: http://www.simonecarletti.com/
13
+ # Source:: http://gist.github.com/gists/6391/
14
+ #
15
+ module HashRecursiveMerge
16
+ #
17
+ # Recursive version of Hash#merge!
18
+ #
19
+ # Adds the contents of +other_hash+ to +hsh+,
20
+ # merging entries in +hsh+ with duplicate keys with those from +other_hash+.
21
+ #
22
+ # Compared with Hash#merge!, this method supports nested hashes.
23
+ # When both +hsh+ and +other_hash+ contains an entry with the same key,
24
+ # it merges and returns the values from both arrays.
25
+ #
26
+ # h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
27
+ # h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
28
+ # h1.rmerge!(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
29
+ #
30
+ # Simply using Hash#merge! would return
31
+ #
32
+ # h1.merge!(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
33
+ #
34
+ def rmerge!(other_hash)
35
+ merge!(other_hash) do |_key, oldval, newval|
36
+ oldval.class == self.class ? oldval.rmerge!(newval) : newval
37
+ end
38
+ end
39
+
40
+ #
41
+ # Recursive version of Hash#merge
42
+ #
43
+ # Compared with Hash#merge!, this method supports nested hashes.
44
+ # When both +hsh+ and +other_hash+ contains an entry with the same key,
45
+ # it merges and returns the values from both arrays.
46
+ #
47
+ # Compared with Hash#merge, this method provides a different approch
48
+ # for merging nasted hashes.
49
+ # If the value of a given key is an Hash and both +other_hash+ abd +hsh
50
+ # includes the same key, the value is merged instead replaced with
51
+ # +other_hash+ value.
52
+ #
53
+ # h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
54
+ # h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
55
+ # h1.rmerge(h2) #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
56
+ #
57
+ # Simply using Hash#merge would return
58
+ #
59
+ # h1.merge(h2) #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
60
+ #
61
+ def rmerge(other_hash)
62
+ merge(other_hash) do |_key, oldval, newval|
63
+ oldval.class == self.class ? oldval.rmerge(newval) : newval
64
+ end
65
+ end
66
+ end
67
+
68
+ class Hash
69
+ include HashRecursiveMerge
70
+ end
@@ -0,0 +1,48 @@
1
+ require 'sora_geocoding/version'
2
+ require 'sora_geocoding/configuration'
3
+ require 'sora_geocoding/logger'
4
+ require 'sora_geocoding/exceptions'
5
+ require 'sora_geocoding/base'
6
+ require 'sora_geocoding/query'
7
+ require 'sora_geocoding/url'
8
+ require 'sora_geocoding/request'
9
+ require 'sora_geocoding/results/geocoding'
10
+ require 'sora_geocoding/results/yahoo_geocoder'
11
+
12
+ #
13
+ # This library takes into account the number of API calls and address lookup to get the latitude and longitude.
14
+ # The API uses the Geocoding API and the Yahoo! Geocoder API.
15
+ #
16
+ module SoraGeocoding
17
+ #
18
+ # Search for information about an address or a set of coordinates.
19
+ #
20
+ def self.search(query, options = {})
21
+ query = SoraGeocoding::Query.new(query, options) unless query.is_a?(SoraGeocoding::Query)
22
+ query.nil? ? nil : query.execute
23
+ end
24
+
25
+ #
26
+ # Look up the coordinates of the given street or IP address.
27
+ #
28
+ def self.coordinates(address, options = {})
29
+ results = search(address, options)
30
+ return if results.nil?
31
+
32
+ { site: results[:site], coordinates: site_specific_coordinates(results[:site], results[:data]) }
33
+ end
34
+
35
+ class << self
36
+ private
37
+ def site_specific_coordinates(site, data)
38
+ SoraGeocoding::Results.const_get(site_map[site]).new(data).coordinates
39
+ end
40
+
41
+ def site_map
42
+ {
43
+ 'yahoo' => 'YahooGeocoder',
44
+ 'geocoding' => 'Geocoding'
45
+ }
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,31 @@
1
+ require 'timeout'
2
+
3
+ module SoraGeocoding
4
+ class Base
5
+ #
6
+ # Symbol which is used in configuration to refer to this Lookup.
7
+ #
8
+ def handle
9
+ str = self.class.to_s
10
+ str[str.rindex(':') + 1..-1].gsub(/([a-z\d]+)([A-Z])/, '\1_\2').downcase.to_sym
11
+ end
12
+
13
+ #
14
+ # specific config data
15
+ #
16
+ def configuration
17
+ SoraGeocoding.config_for_lookup(handle)
18
+ end
19
+
20
+ #
21
+ # Raise exception.
22
+ # Return false if exception not raised.
23
+ #
24
+ def raise_error(error, message = nil)
25
+ exceptions = configuration.always_raise
26
+ raise error, message if (exceptions == :all) || exceptions.include?(error.is_a?(Class) ? error : error.class)
27
+
28
+ false
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,119 @@
1
+ require 'singleton'
2
+ require 'hash_recursive_merge'
3
+
4
+ module SoraGeocoding
5
+ class ConfigurationHash < Hash
6
+ include HashRecursiveMerge
7
+
8
+ def method_missing(method, *args, &block)
9
+ key?(method) ? self[method] : super
10
+ end
11
+
12
+ def respond_to_missing?(method, include_private)
13
+ key?(method) ? true : super
14
+ end
15
+ end
16
+
17
+ #
18
+ # Configuration options should be set by passing a hash:
19
+ #
20
+ # SoraGeocoding.configure(
21
+ # :timeout => 5,
22
+ # :site => 'yahoo',
23
+ # :yahoo_appid => '2a9fsa983jaslfj982fjasd'
24
+ # )
25
+ #
26
+ def self.configure(options = nil)
27
+ options ? Configuration.instance.configure(options) : config
28
+ end
29
+
30
+ #
31
+ # Read-only access to the singleton's config data.
32
+ #
33
+ def self.config
34
+ Configuration.instance.data
35
+ end
36
+
37
+ #
38
+ # Read-only access to specific config data.
39
+ #
40
+ def self.config_for_lookup(lookup_name)
41
+ data = config.clone
42
+ data.select! { |key, _value| Configuration::OPTIONS.include?(key) }
43
+ data.merge!(config[lookup_name]) if config.key?(lookup_name)
44
+ data
45
+ end
46
+
47
+ class Configuration
48
+ include Singleton
49
+
50
+ OPTIONS = %i[
51
+ timeout
52
+ http_headers
53
+ use_https
54
+ http_proxy
55
+ https_proxy
56
+ basic_auth
57
+ site
58
+ yahoo_appid
59
+ logger_level
60
+ always_raise
61
+ ].freeze
62
+
63
+ attr_accessor :data
64
+
65
+ def self.set_defaults
66
+ instance.set_defaults
67
+ end
68
+
69
+ OPTIONS.each do |o|
70
+ define_method o do
71
+ @data[o]
72
+ end
73
+ define_method "#{o}=" do |value|
74
+ @data[o] = value
75
+ end
76
+ end
77
+
78
+ def configure(options)
79
+ @data.rmerge!(options)
80
+ end
81
+
82
+ def initialize
83
+ @data = SoraGeocoding::ConfigurationHash.new
84
+ set_defaults
85
+ end
86
+
87
+ def set_defaults
88
+ # options
89
+ @data[:timeout] = 3 # timeout (secs)
90
+ @data[:http_headers] = {} # HTTP headers
91
+ @data[:use_https] = false # use HTTPS for requests?
92
+ @data[:http_proxy] = nil # HTTP proxy server (user:pass@host:port)
93
+ @data[:https_proxy] = nil # HTTPS proxy server (user:pass@host:port)
94
+ @data[:basic_auth] = {} # user and password for basic auth ({:user => "user", :password => "password"})
95
+ @data[:site] = nil
96
+ @data[:yahoo_appid] = nil # API key for Yahoo Geocoder API
97
+ @data[:logger_level] = ::Logger::WARN # log level, if kernel logger is used
98
+
99
+ # [supports]
100
+ # - :all
101
+ # - SocketError
102
+ # - Timeout::Error
103
+ @data[:always_raise] = []
104
+ end
105
+
106
+ instance_eval(OPTIONS.map do |option|
107
+ o = option.to_s
108
+ <<-INSTANCE_DATA
109
+ def #{o}
110
+ instance.data[:#{o}]
111
+ end
112
+
113
+ def #{o}=(value)
114
+ instance.data[:#{o}] = value
115
+ end
116
+ INSTANCE_DATA
117
+ end.join("\n\n"))
118
+ end
119
+ end
@@ -0,0 +1,44 @@
1
+ require 'timeout'
2
+
3
+ module SoraGeocoding
4
+ class ConfigurationError < StandardError
5
+ end
6
+
7
+ class ResponseParseError < StandardError
8
+ attr_reader :response
9
+
10
+ def initialize(response)
11
+ @response = response
12
+ end
13
+ end
14
+
15
+ class InvalidRequest < StandardError
16
+ end
17
+
18
+ class RequestDenied < StandardError
19
+ end
20
+
21
+ class PaymentRequiredError < StandardError
22
+ end
23
+
24
+ class ForbiddenError < StandardError
25
+ end
26
+
27
+ class NotFoundError < StandardError
28
+ end
29
+
30
+ class ProxyAuthenticationRequiredError < StandardError
31
+ end
32
+
33
+ class OverQueryLimitError < StandardError
34
+ end
35
+
36
+ class ServiceUnavailable < StandardError
37
+ end
38
+
39
+ class Timeout < ::Timeout::Error
40
+ end
41
+
42
+ class NetworkError < StandardError
43
+ end
44
+ end