mq_reader 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 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