Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ Note that this endpoint performs no geocoding; it merely formats a single provid

### Additional fields

Geocodio has added support for retrieving [additional fields][fields] when geocoding or reverse geocoding. To request these fields, pass an options hash to either `#geocode` or `#reverse_geocode`. Possible fields include `cd` or `cd113`, `stateleg`, `school`, and `timezone`:
Geocodio supports retrieval of [additional fields][fields] when geocoding or reverse geocoding. To request these fields, pass an options hash to either `#geocode` or `#reverse_geocode`. Possible fields include `cd`, `stateleg`, `school`, `census`, and `timezone`:

```ruby
address = geocodio.geocode(['54 West Colorado Boulevard Pasadena CA 91105'], fields: %w[cd stateleg school timezone]).best
address = geocodio.geocode(['54 West Colorado Boulevard Pasadena CA 91105'], fields: %w[cd stateleg school census timezone]).best

address.congressional_districts
# => #<Geocodio::CongressionalDistrict:0x007fa3c15f41c0 @name="Congressional District 27" @district_number=27 @congress_number=113 @congress_years=2013..2015>
Expand All @@ -115,8 +115,25 @@ address.timezone
# => #<Geocodio::Timezone:0x007fa3c15f41c0 @name="PST" @utc_offset=-8 @observes_dst=true>
address.timezone.observes_dst?
# => true

address.census
# => {"2019"=>#<Geocodio::CensusYear:0x00007ff59a24a800 ...>}
address.census.years
# => ["2019"]
address.census.latest
# => #<Geocodio::CensusYear:0x00007ff59a24a800 @census_year=2019, @state_fips="06", @county_fips="06037", @tract_code="463700", @block_code="2001", @block_group="2", @full_fips="060374637002001", @source="US Census Bureau", @place, @metro_micro_statistical_area, @combined_statistical_area, @metropolitan_division>
address.census.latest.place
# => #<Geocodio::Place:0x00007ff59a24a7b0 @name="Pasadena", @fips="0656000">
address.census.latest.metro_micro_statistical_area # or the shorthand alias .msa
# => #<Geocodio::StatisticalArea:0x00007ff59a24a788 @name="Los Angeles-Long Beach-Anaheim, CA", @area_code="31080", @type="metropolitan">
address.census.latest.combined_statistical_area # or the shorthand alias .csa
# => #<Geocodio::StatisticalArea:0x00007ff59a24a738 @name="Los Angeles-Long Beach, CA", @area_code="348", @type=nil>
address.census.latest.metropolitan_division
# => #<Geocodio::StatisticalArea:0x00007ff59a24a710 @name="Los Angeles-Long Beach-Glendale, CA", @area_code="31084", @type=nil>
```

The `cd` field requests district information for the current congress (116th as of November 2020). Information for a specific congress can be retrieved by specifying `cd113`, `cd114`, ... `cd117` (see the [Geocod.io documentation][districts] for details). Similarly, the `census` field requests information for the most recent census year (2019 as of November 2020), but one or more specific vintages of census data can be retrieved by specifying `census2010`, `census2011`, ... `census2019` (see the [Geocod.io documentation][census] for details).

## Contributing

1. Fork it ( http://github.com/davidcelis/geocodio/fork )
Expand All @@ -125,5 +142,7 @@ address.timezone.observes_dst?
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request

[geocod.io]: http://geocod.io/
[fields]: http://geocod.io/docs/?ruby#toc_17
[geocod.io]: https://www.geocod.io/
[fields]: https://www.geocod.io/docs/?ruby#fields
[districts]: https://www.geocod.io/docs/?ruby#congressional-districts
[census]: https://www.geocod.io/docs/?ruby#census-block-tract-fips-codes-amp-msa-csa-codes
10 changes: 10 additions & 0 deletions lib/geocodio/address.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require 'geocodio/congressional_district'
require 'geocodio/school_district'
require 'geocodio/state_legislative_district'
require 'geocodio/census'
require 'geocodio/timezone'

module Geocodio
Expand All @@ -16,6 +17,8 @@ class Address
:unified_school_district, :elementary_school_district,
:secondary_school_district

attr_reader :census

attr_reader :timezone

# How accurate geocod.io deemed this result to be given the original query.
Expand Down Expand Up @@ -64,6 +67,7 @@ def set_additional_fields(fields)
set_congressional_districts(fields['congressional_districts']) if fields['congressional_districts']
set_legislative_districts(fields['state_legislative_districts']) if fields['state_legislative_districts']
set_school_districts(fields['school_districts']) if fields['school_districts']
set_census(fields['census']) if fields['census']
set_timezone(fields['timezone']) if fields['timezone']
end

Expand Down Expand Up @@ -91,6 +95,12 @@ def set_school_districts(schools)
end
end

def set_census(census)
return if census.empty?

@census = Census.new(census)
end

def set_timezone(timezone)
return if timezone.empty?

Expand Down
25 changes: 25 additions & 0 deletions lib/geocodio/census.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Census is a hash of Geocodio::CensusYear objects returned from a query,
# indexed by census year represented as a string. Typically an individual
# object would be referenced by the #latest method.

require 'geocodio/census_year'

module Geocodio
class Census < ::Hash

def initialize(payload = {})
super()
replace Hash[payload.map { |year, data| [year, Geocodio::CensusYear.new(data)] }]
end

alias :years :keys

# Returns census data for the most recent year retrieved.
#
# @return [Geocodio::CensusYear] data for the most recent year
def latest
return nil if empty?
self[keys.max]
end
end
end
49 changes: 49 additions & 0 deletions lib/geocodio/census_year.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require 'geocodio/place'
require 'geocodio/statistical_area'

module Geocodio
class CensusYear
attr_reader :census_year
attr_reader :state_fips
attr_reader :county_fips
attr_reader :tract_code
attr_reader :block_code
attr_reader :block_group
attr_reader :full_fips
attr_reader :place
attr_reader :metro_micro_statistical_area
attr_reader :combined_statistical_area
attr_reader :metropolitan_division
attr_reader :source

alias :msa :metro_micro_statistical_area
alias :csa :combined_statistical_area

def initialize(payload = {})
@census_year = payload['census_year']
@state_fips = payload['state_fips']
@county_fips = payload['county_fips']
@tract_code = payload['tract_code']
@block_code = payload['block_code']
@block_group = payload['block_group']
@full_fips = payload['full_fips']
@source = payload['source']

if payload['place']
@place = Place.new(payload['place'])
end

if payload['metro_micro_statistical_area']
@metro_micro_statistical_area = StatisticalArea.new(payload['metro_micro_statistical_area'])
end

if payload['combined_statistical_area']
@combined_statistical_area = StatisticalArea.new(payload['combined_statistical_area'])
end

if payload['metropolitan_division']
@metropolitan_division = StatisticalArea.new(payload['metropolitan_division'])
end
end
end
end
9 changes: 5 additions & 4 deletions lib/geocodio/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ class Client
:delete => Net::HTTP::Delete
}
HOST = 'api.geocod.io'
BASE_PATH = '/v1.2'
PORT = 80
BASE_PATH = '/v1.6'
PORT = 443

def initialize(api_key = ENV['GEOCODIO_API_KEY'])
@api_key = api_key
Expand All @@ -31,7 +31,7 @@ def initialize(api_key = ENV['GEOCODIO_API_KEY'])
#
# @param [Array<String>] addresses one or more String addresses
# @param [Hash] options an options hash
# @option options [Array] :fields a list of option fields to request (possible: "cd" or "cd113", "stateleg", "school", "timezone")
# @option options [Array] :fields a list of option fields to request (possible: "cd" or "cd113", "stateleg", "school", "census", "timezone")
# @return [Geocodio::Address, Array<Geocodio::AddressSet>] One or more Address Sets
def geocode(addresses, options = {})
if addresses.size < 1
Expand All @@ -52,7 +52,7 @@ def geocode(addresses, options = {})
#
# @param [Array<String>, Array<Hash>] coordinates one or more pairs of coordinates
# @param [Hash] options an options hash
# @option options [Array] :fields a list of option fields to request (possible: "cd" or "cd113", "stateleg", "school", "timezone")
# @option options [Array] :fields a list of option fields to request (possible: "cd" or "cd113", "stateleg", "school", "census", "timezone")
# @return [Geocodio::Address, Array<Geocodio::AddressSet>] One or more Address Sets
def reverse_geocode(coordinates, options = {})
if coordinates.size < 1
Expand Down Expand Up @@ -142,6 +142,7 @@ def request(method, path, options)
end

http = Net::HTTP.new HOST, PORT
http.use_ssl = true
http.read_timeout = options[:timeout] if options[:timeout]
res = http.start { http.request(req) }

Expand Down
11 changes: 11 additions & 0 deletions lib/geocodio/place.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Geocodio
class Place
attr_reader :name
attr_reader :fips

def initialize(payload = {})
@name = payload['name']
@fips = payload['fips']
end
end
end
13 changes: 13 additions & 0 deletions lib/geocodio/statistical_area.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module Geocodio
class StatisticalArea
attr_reader :name
attr_reader :area_code
attr_reader :type

def initialize(payload = {})
@name = payload['name']
@area_code = payload['area_code']
@type = payload['type']
end
end
end
2 changes: 1 addition & 1 deletion lib/geocodio/version.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Geocodio
class Version
MAJOR = 3
MINOR = 0
MINOR = 1
PATCH = 0

def self.to_s
Expand Down
2 changes: 1 addition & 1 deletion spec/address_set_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
end

it 'has a size' do
expect(address_set.size).to eq(2)
expect(address_set.size).to eq(3)
end

it 'has a best' do
Expand Down
6 changes: 5 additions & 1 deletion spec/address_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@
context 'with additional fields' do
subject(:address) do
VCR.use_cassette('geocode_with_fields') do
geocodio.geocode(['54 West Colorado Boulevard Pasadena CA 91105'], fields: %w[cd stateleg school timezone]).best
geocodio.geocode(['54 West Colorado Boulevard Pasadena CA 91105'], fields: %w[cd stateleg school census timezone]).best
end
end

Expand Down Expand Up @@ -219,6 +219,10 @@
expect(address.secondary_school_district).to be_nil
end

it 'has census msa/csa/fips codes' do
expect(address.census).to be_a(Geocodio::Census)
end

it 'has a timezone' do
expect(address.timezone).to be_a(Geocodio::Timezone)
end
Expand Down
20 changes: 20 additions & 0 deletions spec/census_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'spec_helper'

describe Geocodio::Census do
let(:geocodio) { Geocodio::Client.new }

subject(:census) do
VCR.use_cassette('geocode_with_census') do
geocodio.geocode(['54 West Colorado Boulevard Pasadena CA 91105'], fields: %w[census2010 census2019]).best.census
end
end

it 'has years' do
expect(census.years).to eq(%w[2010 2019])
end

it 'has latest' do
expect(census.latest).to be_a(Geocodio::CensusYear)
expect(census.latest.census_year).to eql(2019)
end
end
62 changes: 62 additions & 0 deletions spec/census_year_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
require 'spec_helper'

describe Geocodio::CensusYear do
let(:geocodio) { Geocodio::Client.new }

subject(:census) do
VCR.use_cassette('geocode_with_fields') do
geocodio.geocode(['54 West Colorado Boulevard Pasadena CA 91105'], fields: %w[cd stateleg school census timezone]).best.census.latest
end
end

it 'has a census_year' do
expect(census.census_year).to eql(2019)
end

it 'has a state_fips' do
expect(census.state_fips).to eq('06')
end

it 'has a county_fips' do
expect(census.county_fips).to eq('06037')
end

it 'has a tract_code' do
expect(census.tract_code).to eq('463700')
end

it 'has a block_code' do
expect(census.block_code).to eq('2001')
end

it 'has a block_group' do
expect(census.block_group).to eq('2')
end

it 'has a full_fips' do
expect(census.full_fips).to eq('060374637002001')
end

it 'has a place' do
expect(census.place).to be_a(Geocodio::Place)
end

it 'has a metro_micro_statistical_area' do
expect(census.metro_micro_statistical_area).to be_a(Geocodio::StatisticalArea)
expect(census.msa).to be(census.metro_micro_statistical_area)
end

it 'has a combined_statistical_area' do
expect(census.combined_statistical_area).to be_a(Geocodio::StatisticalArea)
expect(census.csa).to be(census.combined_statistical_area)
end

it 'has a metropolitan_division' do
expect(census.metropolitan_division).to be_a(Geocodio::StatisticalArea)
end

it 'has a source' do
expect(census.source).to eq('US Census Bureau')
end

end
Loading