mq_reader 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 213f8ef4d130b18d54d5dde286ef08ad5984faf7
4
+ data.tar.gz: 1828e04bf2bbf9d1f3c2ebf914a3b3220977a2c5
5
+ SHA512:
6
+ metadata.gz: 01b19271c4ee892c80ca975fad87dd6b205e666888beaf631eaa891b2535779251e3044db008f9112bc94decdb4cea38ed11f51890fb5fcf34822dce176bb04f
7
+ data.tar.gz: 2b327a7967b10d8c2cb04d508048ef2ea3358347253672bddf551840c3f1aea03ae90a3b28871a5c18ee2bea1a1d3cadf6ec20927c2c7a815b776ecc5f9c331d
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.test_files = FileList['spec/mq_reader/*_spec.rb']
5
+ t.verbose = true
6
+ end
7
+
8
+ task :default => :test
data/lib/mq_reader.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "httparty"
2
+ require "mq_reader/mq_reader"
3
+ require "cgi"
@@ -0,0 +1,149 @@
1
+ module MQReader
2
+
3
+ BASE_URI = 'http://open.mapquestapi.com'
4
+ GEOCODING_PATH = '/geocoding/v1/address'
5
+
6
+ module ClassMethods
7
+
8
+ @options = []
9
+
10
+ # Geocode a address.
11
+ # This method takes an address as a string and performs the geocoding against mapquest's api.
12
+ # The options hash can have any option accepted by the mapquest geocoding api.
13
+ # The options key can be written ruby-style with underscores, they are transformed to mapquests format.
14
+ # If in the future a new option is added to the api by mapquest, you can add it in the options hash and it will work.
15
+ #
16
+ # @param [String] address to geocode
17
+ # @param [Hash] options for mapquest geocoding service
18
+ def geocode_address(address, options = {})
19
+ path = GEOCODING_PATH
20
+ params = ({ location: CGI::escape(address) }.merge!(to_mapquest_notation(options) ))
21
+ MQGeocode.new(send_get_to_mapquest(path, params))
22
+ end
23
+
24
+ private
25
+
26
+ # Method that posts to the mapquest geocoding api
27
+ #
28
+ # @params [String] path to the geocoding api. /geocoding/v1..
29
+ # @params [Hash] params to be sent with the request. See http://open.mapquestapi.com/geocoding/ for params details.
30
+ #
31
+ # @return [String] with geocoding response body.
32
+ def send_get_to_mapquest(path, params)
33
+ self.get(BASE_URI + path, query: { key: MQReader.configuration.api_key}.merge!(params)).body
34
+ end
35
+
36
+ # Turns underscore keys into mapquest's camelized keys
37
+ # I belive a good ruby api wrapper should let the developer write in a rubyish way.
38
+ # Mapquest accepts options that are camelcased and start with a lowercase letter.
39
+ #
40
+ # @param [Hash] options to turn into mapquest's key format
41
+ #
42
+ # @return [Hash] options hash with mapquest's key format
43
+ def to_mapquest_notation(options)
44
+ Hash[options.map{ |k, v| [camelize_string(k.to_s), v] }]
45
+ end
46
+ end
47
+
48
+ module UtilMethods
49
+ # Same as camelize(:lower) in ActiveSupport
50
+ #
51
+ # @param [String] string to be camelized
52
+ #
53
+ # @return [String] camelized string
54
+ #
55
+ # Example
56
+ # camelize_string("a_long_string") # => "aLongString"
57
+ def camelize_string(string)
58
+ string.split("_").each_with_index {|s, i| s.capitalize! unless i == 0 }.join("")
59
+ end
60
+ end
61
+
62
+ #Extend the module on inclusion.
63
+ #Include Httparty and prevent encoding the api_key(Already encoded by mapquest).
64
+ def self.included(base)
65
+ base.extend ClassMethods
66
+ base.extend UtilMethods
67
+ base.send :include, HTTParty
68
+ # Avoid encoding the api key
69
+ base.query_string_normalizer proc { |query|
70
+ query.map do |key, value|
71
+ "#{key}=#{value}"
72
+ end.join('&')
73
+ }
74
+ end
75
+
76
+ # Configuration Class
77
+ # Right now it's only used to set the API key from the application that's using the gem.
78
+ class Configuration
79
+ attr_accessor :api_key
80
+ end
81
+
82
+ class << self
83
+ attr_accessor :configuration
84
+ end
85
+
86
+ def self.configuration
87
+ @configuration ||= Configuration.new
88
+ end
89
+
90
+ def self.configure
91
+ yield(configuration)
92
+ end
93
+
94
+ # Class used to be able to call #geocode_address directly.
95
+ class BaseClass
96
+ include MQReader
97
+ end
98
+
99
+ def self.geocode_address(*args)
100
+ BaseClass.geocode_address(*args)
101
+ end
102
+
103
+ # Class to handle the response from the mapquest api
104
+ #
105
+ # Provides methods to get every value from the geocoded address.
106
+ class MQGeocode
107
+ attr_reader :street, :city, :zip, :county, :state, :country, :lat, :lng, :raw_geocode
108
+
109
+ def initialize(json_geocode)
110
+ @raw_geocode = JSON.parse(json_geocode)
111
+ raise StandardError, "The request raised an error: #{@raw_geocode['info']['messages']}" if @raw_geocode['info']['statuscode'] != 0
112
+ return if @raw_geocode['results'].first['locations'].empty?
113
+ @lng,@lat = lat_lng_values
114
+ @street = value('street')
115
+ @city = value('adminArea5')
116
+ @county = value('adminArea4')
117
+ @state = value('adminArea3')
118
+ @country = value('adminArea1')
119
+ @zip = value('postalCode')
120
+ @type = value('type')
121
+ @geocode_quality = value('geocodeQuality')
122
+ @side_of_street = value('sideOfStreet')
123
+ end
124
+
125
+ def address_found?
126
+ @raw_geocode['results'].first['locations'].any?
127
+ end
128
+
129
+ private
130
+
131
+ # Get the value of a field from the respond
132
+ def value(field)
133
+ @raw_geocode['results'].first['locations'].first[field]
134
+ end
135
+
136
+ # Get the latitude and longitude from the response
137
+ def lat_lng_values
138
+ latLng = value('latLng')
139
+ return [latLng['lng'],latLng['lat']]
140
+ end
141
+
142
+ # Use method_missing to define accesors for any response attributes that might not be listed in #initialize
143
+ # This accesors are rubyish(underscore notation).
144
+ def method_missing(method_sym, *arguments, &block)
145
+ result = send(:value, BaseClass.camelize_string(method_sym.to_s))
146
+ result.empty? ? super : result
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,3 @@
1
+ module MQReader
2
+ VERSION = "0.0.1"
3
+ end
data/mq_reader.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "mq_reader"
3
+ s.version = "0.0.1"
4
+ s.summary = "Mapquest api wrapper"
5
+ s.date = "2013-02-18"
6
+ s.description = "This is a wrapper for mapquest's geocoding api."
7
+ s.authors = ["Santiago Piria"]
8
+ s.email = ["santiago.piria@gmail.com"]
9
+ s.homepage = "http://rubylearning.org/"
10
+ s.files = %w[Rakefile mq_reader.gemspec]
11
+ s.files += Dir.glob('lib/**/*.rb')
12
+ s.files += Dir.glob('spec/**/*')
13
+ s.require_paths = %w[lib]
14
+ s.test_files = Dir.glob('spec/**/*')
15
+ s.add_dependency 'httparty', '0.13.1'
16
+ s.license = 'MIT'
17
+ end
@@ -0,0 +1 @@
1
+ {"results":[{"locations":[{"latLng":{"lng":-56.15989,"lat":-34.889265},"adminArea4":"","adminArea5Type":"City","adminArea4Type":"County","adminArea5":"Montevideo","street":"Avenida 8 de Octubre 2710","adminArea1":"UY","adminArea3":"Montevideo","type":"s","displayLatLng":{"lng":-56.15989,"lat":-34.889265},"linkId":0,"postalCode":"11600","sideOfStreet":"N","dragPoint":false,"adminArea1Type":"Country","geocodeQuality":"POINT","geocodeQualityCode":"P1XXX","mapUrl":"http://open.mapquestapi.com/staticmap/v4/getmap?key=Fmjtd|luur2g61nl,bl=o5-9az25f&type=map&size=225,160&pois=purple-1,-34.8892649,-56.1598895,0,0|&center=-34.8892649,-56.1598895&zoom=15&rand=1680921967","adminArea3Type":"State"}],"providedLocation":{"location":"2710 Avenida 8 de Octubre, Montevideo, Uruguay"}}],"options":{"ignoreLatLngInput":false,"maxResults":2,"thumbMaps":true},"info":{"copyright":{"text":"© 2014 MapQuest, Inc.","imageUrl":"http://api.mqcdn.com/res/mqlogo.gif","imageAltText":"© 2014 MapQuest, Inc."},"statuscode":0,"messages":[]}}
@@ -0,0 +1 @@
1
+ {"results":[{"locations":[],"providedLocation":{"location":"I INVENTEND THIS"}}],"options":{"ignoreLatLngInput":false,"maxResults":2,"thumbMaps":true},"info":{"copyright":{"text":"© 2014 MapQuest, Inc.","imageUrl":"http://api.mqcdn.com/res/mqlogo.gif","imageAltText":"© 2014 MapQuest, Inc."},"statuscode":0,"messages":[]}}
@@ -0,0 +1,126 @@
1
+ require_relative '../spec_helper'
2
+ describe MQReader do
3
+
4
+ before(:each) do
5
+ MQReader.configure do |config|
6
+ config.api_key = YOUR_API_KEY
7
+ end
8
+ end
9
+
10
+ describe 'ClassMethods' do
11
+
12
+ before do
13
+ stub_get_geocode_with('address_found.json')
14
+ end
15
+
16
+ describe '#geocode_address' do
17
+ context 'address found' do
18
+ it 'should return MQGeocode object with attributes' do
19
+ geocode_obj = MQReader.geocode_address("2710 Avenida 8 de Octubre, Montevideo, Uruguay", { max_results: 2 })
20
+ expect(geocode_obj.class).to eq(MQReader::MQGeocode)
21
+ expect(geocode_obj.lat).to eq(-34.889265)
22
+ expect(geocode_obj.lng).to eq(-56.15989)
23
+ expect(geocode_obj.street).to eq('Avenida 8 de Octubre 2710')
24
+ expect(geocode_obj.geocode_quality).to eq('POINT')
25
+ expect(geocode_obj.country).to eq('UY')
26
+ expect(geocode_obj.geocode_quality_code).to eq('P1XXX')
27
+ expect(geocode_obj.address_found?).to be_true
28
+ end
29
+ end
30
+ context 'address not found' do
31
+ it 'should return MQGeocode object with no attributes except raw_geocode' do
32
+ stub_get_geocode_with('address_not_found.json')
33
+ geocode_obj = MQReader.geocode_address("2710 Avenida 8 de Octubre, Montevideo, Uruguay", { max_results: 2 })
34
+ expect(geocode_obj.class).to eq(MQReader::MQGeocode)
35
+ expect(geocode_obj.street).to be_nil
36
+ expect(geocode_obj.address_found?).to be_false
37
+ end
38
+ end
39
+ it 'should call #geocode_address on BaseClass' do
40
+ MQReader::BaseClass.should_receive(:geocode_address)
41
+ MQReader.geocode_address('home', max_results: 2)
42
+ end
43
+ it "should call #send_get_to_mapquest with correct params and MQGeocode#new" do
44
+ MQReader::BaseClass.should_receive(:send_get_to_mapquest).with(MQReader::GEOCODING_PATH, { location: 'home', 'maxResults' => 2 })
45
+ MQReader::MQGeocode.should_receive(:new)
46
+ MQReader.geocode_address('home', max_results: 2)
47
+ end
48
+ end
49
+
50
+ describe '#send_get_to_mapquest' do
51
+ it 'should call #get on BaseClass, and the call #body on the result of #get' do
52
+ obj = double('object')
53
+ MQReader::BaseClass.should_receive(:get).with(MQReader::BASE_URI + 'path', { query: { key: MQReader.configuration.api_key, param: 'something' } }).and_return(obj)
54
+ obj.should_receive(:body)
55
+ MQReader::BaseClass.send(:send_get_to_mapquest, 'path', { param: 'something' })
56
+ end
57
+ end
58
+
59
+ describe '#to_mapquest_notation' do
60
+ it 'should transform keys' do
61
+ expect(MQReader::BaseClass.send(:to_mapquest_notation, ({}))).to eq({})
62
+ expect(MQReader::BaseClass.send(:to_mapquest_notation, ({a_key: 'value', another_key: 'value'}))).to eq({'aKey' => 'value', 'anotherKey' => 'value'})
63
+ expect(MQReader::BaseClass.send(:to_mapquest_notation, ({'' => 'value'}))).to eq({'' => 'value'})
64
+ expect(MQReader::BaseClass.send(:to_mapquest_notation, ({a_key: 'value'}))).to eq({'aKey' => 'value'})
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ describe 'UtilMethods' do
71
+ describe 'camelize_string' do
72
+ it 'should camelize string and leave the first character lowercase' do
73
+ expect(MQReader::BaseClass.camelize_string('')).to eq('')
74
+ expect(MQReader::BaseClass.camelize_string('a_long_string')).to eq('aLongString')
75
+ end
76
+ end
77
+ end
78
+
79
+ describe 'configuration' do
80
+ it 'should be possible to set api_key and retrieve it' do
81
+ MQReader.configure do |config|
82
+ config.api_key = "1234567"
83
+ end
84
+ expect(MQReader.configuration.api_key).to eq("1234567")
85
+ end
86
+ end
87
+
88
+ describe 'MQGeocode class' do
89
+
90
+ let(:obj) { MQReader::MQGeocode.new("{\"results\":[{\"locations\":[{\"latLng\":{\"lng\":-56.15989,\"lat\":-34.889265},\"adminArea4\":\"\",\"adminArea5Type\":\"City\",\"adminArea4Type\":\"County\",\"adminArea5\":\"Montevideo\",\"street\":\"Avenida 8 de Octubre 2710\",\"adminArea1\":\"UY\",\"adminArea3\":\"Montevideo\",\"type\":\"s\",\"displayLatLng\":{\"lng\":-56.15989,\"lat\":-34.889265},\"linkId\":0,\"postalCode\":\"11600\",\"sideOfStreet\":\"N\",\"dragPoint\":false,\"adminArea1Type\":\"Country\",\"geocodeQuality\":\"POINT\",\"geocodeQualityCode\":\"P1XXX\",\"mapUrl\":\"http://open.mapquestapi.com/staticmap/v4/getmap?key=Fmjtd|luur2g61nl,bl=o5-9az25f&type=map&size=225,160&pois=purple-1,-34.8892649,-56.1598895,0,0|&center=-34.8892649,-56.1598895&zoom=15&rand=1680921967\",\"adminArea3Type\":\"State\"}],\"providedLocation\":{\"location\":\"2710 Avenida 8 de Octubre, Montevideo, Uruguay\"}}],\"options\":{\"ignoreLatLngInput\":false,\"maxResults\":2,\"thumbMaps\":true},\"info\":{\"copyright\":{\"text\":\"© 2014 MapQuest, Inc.\",\"imageUrl\":\"http://api.mqcdn.com/res/mqlogo.gif\",\"imageAltText\":\"© 2014 MapQuest, Inc.\"},\"statuscode\":0,\"messages\":[]}}") }
91
+
92
+ describe 'intialization' do
93
+ context 'request with errors' do
94
+ it 'should raise an error' do
95
+ expect{MQReader::MQGeocode.new("{\"info\":{\"statuscode\":1,\"messages\":[\"The request failed.\"]}}")}.to raise_error(StandardError)
96
+ end
97
+ end
98
+
99
+ context 'request with no errors' do
100
+ it 'should have methods to access the geocode values' do
101
+ expect(obj.street).to eq('Avenida 8 de Octubre 2710')
102
+ expect(obj.geocode_quality).to eq('POINT')
103
+ expect(obj.address_found?).to be_true
104
+ end
105
+ it 'should have methods to access the variables that are not defined in the class. Via method_missing' do
106
+ expect(obj.street).to eq('Avenida 8 de Octubre 2710')
107
+ expect(obj.geocode_quality_code).to eq('P1XXX')
108
+ expect(obj.side_of_street).to eq('N')
109
+ end
110
+ end
111
+ end
112
+
113
+ describe 'address_found?' do
114
+ context 'address found' do
115
+ it 'should return true' do
116
+ expect(obj.address_found?).to be_true
117
+ end
118
+ end
119
+ context 'address not found' do
120
+ it 'should return false' do
121
+ expect(MQReader::MQGeocode.new("{\"results\":[{\"locations\":[]}], \"info\":{\"statuscode\":0}}").address_found?).to be_false
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,20 @@
1
+ require_relative '../lib/mq_reader'
2
+
3
+ require 'minitest/autorun'
4
+ require 'webmock/rspec'
5
+ require 'cgi'
6
+ WebMock.disable_net_connect!
7
+
8
+ def fixture_path
9
+ File.expand_path('../fixtures', __FILE__)
10
+ end
11
+
12
+ def fixture(file)
13
+ File.new(fixture_path + '/' + file)
14
+ end
15
+
16
+ YOUR_API_KEY = "Fmjtd%7Cluur2g61nl%2Cbl%3Do5-9az25f"
17
+
18
+ def stub_get_geocode_with(fixture)
19
+ stub_request(:get, "http://open.mapquestapi.com/geocoding/v1/address?key=#{CGI.unescape(YOUR_API_KEY)}&location=2710%20Avenida%208%20de%20Octubre,%20Montevideo,%20Uruguay&maxResults=2").to_return(:status => 200, :body => fixture(fixture))
20
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mq_reader
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Santiago Piria
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-02-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.13.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.13.1
27
+ description: This is a wrapper for mapquest's geocoding api.
28
+ email:
29
+ - santiago.piria@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - Rakefile
35
+ - lib/mq_reader.rb
36
+ - lib/mq_reader/mq_reader.rb
37
+ - lib/mq_reader/version.rb
38
+ - mq_reader.gemspec
39
+ - spec/fixtures/address_found.json
40
+ - spec/fixtures/address_not_found.json
41
+ - spec/mq_reader/mq_reader_spec.rb
42
+ - spec/spec_helper.rb
43
+ homepage: http://rubylearning.org/
44
+ licenses:
45
+ - MIT
46
+ metadata: {}
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubyforge_project:
63
+ rubygems_version: 2.2.2
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: Mapquest api wrapper
67
+ test_files:
68
+ - spec/fixtures/address_found.json
69
+ - spec/fixtures/address_not_found.json
70
+ - spec/mq_reader/mq_reader_spec.rb
71
+ - spec/spec_helper.rb