us_geo 1.0.3 → 2.0.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 +4 -4
- data/CHANGELOG.md +82 -0
- data/MIT_LICENSE.txt +21 -0
- data/README.md +77 -60
- data/UPDATING_TO_VERSION_2.md +172 -0
- data/VERSION +1 -0
- data/db/migrate/20190221054200_create_regions.rb +4 -2
- data/db/migrate/20190221054300_create_divisions.rb +4 -2
- data/db/migrate/20190221054400_create_states.rb +4 -2
- data/db/migrate/20190221054500_create_combined_statistical_areas.rb +4 -2
- data/db/migrate/20190221054600_create_core_based_statistical_areas.rb +4 -2
- data/db/migrate/20190221054650_create_metropolitan_divisions.rb +4 -2
- data/db/migrate/20190221054700_create_counties.rb +4 -3
- data/db/migrate/20190221054800_create_zctas.rb +4 -2
- data/db/migrate/20190221054900_create_zcta_counties.rb +4 -2
- data/db/migrate/20190221055000_create_urban_areas.rb +4 -2
- data/db/migrate/20190221055100_create_urban_area_counties.rb +4 -4
- data/db/migrate/20190221055200_create_zcta_urban_areas.rb +4 -4
- data/db/migrate/20190221060000_create_places.rb +4 -2
- data/db/migrate/20190221061000_create_place_counties.rb +4 -2
- data/db/migrate/20190221062000_create_zcta_places.rb +4 -4
- data/db/migrate/20190221063000_create_county_subdivisions.rb +4 -2
- data/db/migrate/20220722000000_allow_null_zcta_counties_demographics.rb +23 -0
- data/db/migrate/20220722000200_allow_null_zcta_places_demographics.rb +23 -0
- data/db/migrate/20230414000000_add_zcta_primary_place.rb +13 -0
- data/db/migrate/20230414000200_add_demographics_to_regions.rb +28 -0
- data/db/migrate/20230414000300_add_demographics_to_divisions.rb +28 -0
- data/db/migrate/20230414000400_add_demographics_to_states.rb +28 -0
- data/db/migrate/20230414000700_add_short_name_to_core_based_statistical_areas.rb +22 -0
- data/db/migrate/20230414000750_add_short_name_to_combined_statistical_areas.rb +22 -0
- data/db/migrate/20230414000800_create_zcta_mappings.rb +18 -0
- data/db/migrate/20230417000100_create_zcta_county_subdivisions.rb +22 -0
- data/db/migrate/20230417000200_add_unique_name_index_to_county_subdivisions.rb +26 -0
- data/db/migrate/20230417000250_add_zcta_primary_county_subdivision.rb +13 -0
- data/db/migrate/20230417000300_create_urban_area_county_subdivisions.rb +23 -0
- data/db/migrate/20230417000400_allow_null_urban_area_counties_demographics.rb +23 -0
- data/db/migrate/20230417000500_allow_null_zcta_urban_areas_demographics.rb +23 -0
- data/db/migrate/20230417000600_add_additional_time_zone_name_to_counties.rb +13 -0
- data/db/schema.rb +303 -0
- data/explorer_app/.gitattributes +7 -0
- data/explorer_app/.gitignore +34 -0
- data/explorer_app/Gemfile +38 -0
- data/explorer_app/Rakefile +6 -0
- data/explorer_app/app/assets/images/.keep +0 -0
- data/explorer_app/app/assets/stylesheets/application.css +1 -0
- data/explorer_app/app/controllers/application_controller.rb +64 -0
- data/explorer_app/app/controllers/combined_statistical_areas_controller.rb +12 -0
- data/explorer_app/app/controllers/concerns/.keep +0 -0
- data/explorer_app/app/controllers/core_based_statistical_areas_controller.rb +36 -0
- data/explorer_app/app/controllers/counties_controller.rb +22 -0
- data/explorer_app/app/controllers/county_subdivisions_controller.rb +23 -0
- data/explorer_app/app/controllers/divisions_controller.rb +27 -0
- data/explorer_app/app/controllers/home_controller.rb +6 -0
- data/explorer_app/app/controllers/metropolitan_divisions_controller.rb +27 -0
- data/explorer_app/app/controllers/places_controller.rb +23 -0
- data/explorer_app/app/controllers/regions_controller.rb +13 -0
- data/explorer_app/app/controllers/states_controller.rb +25 -0
- data/explorer_app/app/controllers/urban_areas_controller.rb +24 -0
- data/explorer_app/app/controllers/zctas_controller.rb +23 -0
- data/explorer_app/app/helpers/application_helper.rb +137 -0
- data/explorer_app/app/models/application_record.rb +3 -0
- data/explorer_app/app/models/concerns/.keep +0 -0
- data/explorer_app/app/views/combined_statistical_areas/_table.html.erb +18 -0
- data/explorer_app/app/views/combined_statistical_areas/index.html.erb +7 -0
- data/explorer_app/app/views/combined_statistical_areas/show.html.erb +52 -0
- data/explorer_app/app/views/core_based_statistical_areas/_table.html.erb +32 -0
- data/explorer_app/app/views/core_based_statistical_areas/index.html.erb +19 -0
- data/explorer_app/app/views/core_based_statistical_areas/show.html.erb +60 -0
- data/explorer_app/app/views/counties/_table.html.erb +64 -0
- data/explorer_app/app/views/counties/show.html.erb +96 -0
- data/explorer_app/app/views/county_subdivisions/_table.html.erb +48 -0
- data/explorer_app/app/views/county_subdivisions/show.html.erb +84 -0
- data/explorer_app/app/views/divisions/_table.html.erb +24 -0
- data/explorer_app/app/views/divisions/index.html.erb +3 -0
- data/explorer_app/app/views/divisions/show.html.erb +3 -0
- data/explorer_app/app/views/home/index.html.erb +23 -0
- data/explorer_app/app/views/layouts/application.html.erb +34 -0
- data/explorer_app/app/views/metropolitan_divisions/_table.html.erb +42 -0
- data/explorer_app/app/views/metropolitan_divisions/index.html.erb +8 -0
- data/explorer_app/app/views/metropolitan_divisions/show.html.erb +46 -0
- data/explorer_app/app/views/places/_table.html.erb +47 -0
- data/explorer_app/app/views/places/show.html.erb +92 -0
- data/explorer_app/app/views/regions/_table.html.erb +18 -0
- data/explorer_app/app/views/regions/index.html.erb +7 -0
- data/explorer_app/app/views/regions/show.html.erb +3 -0
- data/explorer_app/app/views/shared/_breadcrumbs.html.erb +13 -0
- data/explorer_app/app/views/shared/_demographics_cells.html.erb +5 -0
- data/explorer_app/app/views/shared/_demographics_headers.html.erb +5 -0
- data/explorer_app/app/views/states/_table.html.erb +31 -0
- data/explorer_app/app/views/states/index.html.erb +7 -0
- data/explorer_app/app/views/states/show.html.erb +54 -0
- data/explorer_app/app/views/urban_areas/_table.html.erb +45 -0
- data/explorer_app/app/views/urban_areas/index.html.erb +19 -0
- data/explorer_app/app/views/urban_areas/show.html.erb +68 -0
- data/explorer_app/app/views/zctas/_table.html.erb +60 -0
- data/explorer_app/app/views/zctas/show.html.erb +104 -0
- data/explorer_app/bin/bundle +109 -0
- data/explorer_app/bin/rails +4 -0
- data/explorer_app/bin/rake +4 -0
- data/explorer_app/bin/setup +33 -0
- data/explorer_app/config/application.rb +37 -0
- data/explorer_app/config/boot.rb +3 -0
- data/explorer_app/config/database.yml +13 -0
- data/explorer_app/config/environment.rb +5 -0
- data/explorer_app/config/environments/development.rb +59 -0
- data/explorer_app/config/initializers/filter_parameter_logging.rb +8 -0
- data/explorer_app/config/locales/en.yml +2 -0
- data/explorer_app/config/puma.rb +43 -0
- data/explorer_app/config/routes.rb +56 -0
- data/explorer_app/config.ru +6 -0
- data/explorer_app/db/seeds.rb +7 -0
- data/explorer_app/lib/assets/.keep +0 -0
- data/explorer_app/lib/tasks/.keep +0 -0
- data/explorer_app/log/.keep +0 -0
- data/explorer_app/public/404.html +67 -0
- data/explorer_app/public/422.html +67 -0
- data/explorer_app/public/500.html +66 -0
- data/explorer_app/public/apple-touch-icon-precomposed.png +0 -0
- data/explorer_app/public/apple-touch-icon.png +0 -0
- data/explorer_app/public/favicon.ico +0 -0
- data/explorer_app/public/robots.txt +1 -0
- data/explorer_app/tmp/.keep +0 -0
- data/explorer_app/tmp/pids/.keep +0 -0
- data/lib/tasks/us_geo/us_geo.rake +44 -3
- data/lib/us_geo/area.rb +44 -0
- data/lib/us_geo/base_record.rb +22 -16
- data/lib/us_geo/combined_statistical_area.rb +18 -8
- data/lib/us_geo/core_based_statistical_area.rb +24 -12
- data/lib/us_geo/county.rb +67 -16
- data/lib/us_geo/county_subdivision.rb +43 -7
- data/lib/us_geo/division.rb +17 -7
- data/lib/us_geo/metropolitan_area.rb +1 -5
- data/lib/us_geo/metropolitan_division.rb +17 -9
- data/lib/us_geo/micropolitan_area.rb +1 -5
- data/lib/us_geo/place.rb +61 -11
- data/lib/us_geo/place_county.rb +1 -4
- data/lib/us_geo/population.rb +26 -0
- data/lib/us_geo/region.rb +18 -8
- data/lib/us_geo/state.rb +32 -11
- data/lib/us_geo/urban_area.rb +46 -16
- data/lib/us_geo/urban_area_county.rb +4 -21
- data/lib/us_geo/urban_area_county_subdivision.rb +51 -0
- data/lib/us_geo/urban_cluster.rb +1 -5
- data/lib/us_geo/urbanized_area.rb +1 -5
- data/lib/us_geo/version.rb +1 -1
- data/lib/us_geo/zcta.rb +90 -13
- data/lib/us_geo/zcta_county.rb +5 -22
- data/lib/us_geo/zcta_county_subdivision.rb +51 -0
- data/lib/us_geo/zcta_mapping.rb +35 -0
- data/lib/us_geo/zcta_place.rb +5 -12
- data/lib/us_geo/zcta_urban_area.rb +3 -20
- data/lib/us_geo.rb +34 -31
- data/us_geo.gemspec +36 -0
- metadata +125 -129
- data/Gemfile +0 -5
- data/Gemfile.lock +0 -75
- data/Rakefile +0 -18
- data/db/migrate/20190221054490_create_designated_market_areas.rb +0 -16
- data/lib/us_geo/demographics.rb +0 -25
- data/lib/us_geo/designated_market_area.rb +0 -30
- data/spec/spec_helper.rb +0 -22
- data/spec/us_geo/base_record_spec.rb +0 -67
- data/spec/us_geo/combined_statistical_area_spec.rb +0 -33
- data/spec/us_geo/core_based_statistical_area_spec.rb +0 -56
- data/spec/us_geo/county_spec.rb +0 -131
- data/spec/us_geo/county_subdivision_spec.rb +0 -37
- data/spec/us_geo/demographics_spec.rb +0 -19
- data/spec/us_geo/designated_market_area_spec.rb +0 -29
- data/spec/us_geo/division_spec.rb +0 -37
- data/spec/us_geo/metropolitan_division_spec.rb +0 -41
- data/spec/us_geo/place_county_spec.rb +0 -39
- data/spec/us_geo/place_spec.rb +0 -71
- data/spec/us_geo/region_spec.rb +0 -36
- data/spec/us_geo/state_spec.rb +0 -70
- data/spec/us_geo/urban_area_county_spec.rb +0 -82
- data/spec/us_geo/urban_area_spec.rb +0 -98
- data/spec/us_geo/zcta_county_spec.rb +0 -82
- data/spec/us_geo/zcta_place_spec.rb +0 -82
- data/spec/us_geo/zcta_spec.rb +0 -99
- data/spec/us_geo/zcta_urban_area_spec.rb +0 -82
data/lib/us_geo/county.rb
CHANGED
|
@@ -1,45 +1,70 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module USGeo
|
|
4
|
-
|
|
5
4
|
# County or county equivalent. Counties are composed of zero or more ZCTA's and may
|
|
6
5
|
# belong to a CBSA. The county's significance withing the CBSA is indicated by the
|
|
7
6
|
# central flag which indicates if it is a central or outlying county.
|
|
8
7
|
class County < BaseRecord
|
|
9
|
-
|
|
10
|
-
include
|
|
8
|
+
include Population
|
|
9
|
+
include Area
|
|
11
10
|
|
|
12
11
|
self.primary_key = "geoid"
|
|
13
12
|
|
|
14
|
-
belongs_to :designated_market_area, foreign_key: :dma_code, optional: true, inverse_of: :counties
|
|
15
13
|
belongs_to :core_based_statistical_area, foreign_key: :cbsa_geoid, optional: true, inverse_of: :counties
|
|
16
14
|
belongs_to :metropolitan_division, foreign_key: :metropolitan_division_geoid, optional: true, inverse_of: :counties
|
|
17
15
|
belongs_to :state, foreign_key: :state_code, inverse_of: :counties
|
|
18
16
|
|
|
19
|
-
has_many :subdivisions, foreign_key: :county_geoid, inverse_of: :county, class_name: "USGeo::CountySubdivision"
|
|
17
|
+
has_many :subdivisions, -> { not_removed }, foreign_key: :county_geoid, inverse_of: :county, class_name: "USGeo::CountySubdivision"
|
|
20
18
|
|
|
21
|
-
has_many :zcta_counties, foreign_key: :county_geoid, inverse_of: :county, dependent: :destroy
|
|
22
|
-
has_many :zctas, through: :zcta_counties
|
|
19
|
+
has_many :zcta_counties, -> { not_removed }, foreign_key: :county_geoid, inverse_of: :county, dependent: :destroy
|
|
20
|
+
has_many :zctas, -> { not_removed }, through: :zcta_counties
|
|
23
21
|
|
|
24
22
|
has_many :urban_area_counties, foreign_key: :county_geoid, inverse_of: :county, dependent: :destroy
|
|
25
23
|
has_many :urban_areas, through: :urban_area_counties
|
|
26
24
|
|
|
27
|
-
has_many :place_counties, foreign_key: :county_geoid, inverse_of: :county, dependent: :destroy
|
|
28
|
-
has_many :places, through: :place_counties
|
|
25
|
+
has_many :place_counties, -> { not_removed }, foreign_key: :county_geoid, inverse_of: :county, dependent: :destroy
|
|
26
|
+
has_many :places, -> { not_removed }, through: :place_counties
|
|
29
27
|
|
|
30
28
|
validates :geoid, length: {is: 5}
|
|
31
|
-
validates :name, length: {maximum: 60}
|
|
32
|
-
validates :short_name, length: {maximum: 30}
|
|
29
|
+
validates :name, presence: true, length: {maximum: 60}, uniqueness: {scope: :state_code}
|
|
30
|
+
validates :short_name, presence: true, length: {maximum: 30}, uniqueness: {scope: :state_code}
|
|
33
31
|
validates :state_code, length: {is: 2}
|
|
34
32
|
validates :fips_class_code, length: {is: 2}
|
|
35
33
|
validates :metropolitan_division_geoid, length: {is: 5}, allow_nil: true
|
|
36
34
|
validates :cbsa_geoid, length: {is: 5}, allow_nil: true
|
|
37
|
-
validates :dma_code, length: {is: 3}, allow_nil: true
|
|
38
35
|
validates :land_area, numericality: true, allow_nil: true
|
|
39
36
|
validates :water_area, numericality: true, allow_nil: true
|
|
40
37
|
validates :population, numericality: {only_integer: true}, allow_nil: true
|
|
41
38
|
validates :housing_units, numericality: {only_integer: true}, allow_nil: true
|
|
42
39
|
|
|
40
|
+
# @!attribute geoid
|
|
41
|
+
# @return [String] 5-digit code for the county.
|
|
42
|
+
|
|
43
|
+
# @!attribute name
|
|
44
|
+
# @return [String] Name of the county.
|
|
45
|
+
|
|
46
|
+
# @!attribute short_name
|
|
47
|
+
# @return [String] Short name of the county.
|
|
48
|
+
|
|
49
|
+
# @!attribute state_code
|
|
50
|
+
# @return [String] 2-letter code for the state.
|
|
51
|
+
|
|
52
|
+
# @!attribute fips_class_code
|
|
53
|
+
# @return [String] 2-character FIPS class code.
|
|
54
|
+
|
|
55
|
+
# @!attribute time_zone_name
|
|
56
|
+
# @return [String] Time zone name.
|
|
57
|
+
|
|
58
|
+
# @!attribute time_zone_2_name
|
|
59
|
+
# @return [String] Time zone name.
|
|
60
|
+
|
|
61
|
+
# @!method central?
|
|
62
|
+
# @return [Boolean] True if the county is a central county in the CBSA.
|
|
63
|
+
|
|
64
|
+
# @!method combined_statistical_area
|
|
65
|
+
# @return [USGeo::CombinedStatisticalArea] Combined statistical area that the county belongs to.
|
|
66
|
+
delegate :combined_statistical_area, to: :core_based_statistical_area, allow_nil: true
|
|
67
|
+
|
|
43
68
|
class << self
|
|
44
69
|
def load!(uri = nil)
|
|
45
70
|
location = data_uri(uri || "counties.csv")
|
|
@@ -53,14 +78,14 @@ module USGeo
|
|
|
53
78
|
record.state_code = row["State"]
|
|
54
79
|
record.cbsa_geoid = row["CBSA"]
|
|
55
80
|
record.metropolitan_division_geoid = row["Metropolitan Division"]
|
|
56
|
-
record.dma_code = row["DMA"]
|
|
57
81
|
record.time_zone_name = row["Time Zone"]
|
|
82
|
+
record.time_zone_2_name = row["Time Zone 2"]
|
|
58
83
|
record.fips_class_code = row["FIPS Class"]
|
|
59
84
|
record.central = (row["Central"] == "T")
|
|
60
85
|
record.population = row["Population"]
|
|
61
86
|
record.housing_units = row["Housing Units"]
|
|
62
|
-
record.land_area =
|
|
63
|
-
record.water_area =
|
|
87
|
+
record.land_area = row["Land Area"]
|
|
88
|
+
record.water_area = row["Water Area"]
|
|
64
89
|
record.lat = row["Latitude"]
|
|
65
90
|
record.lng = row["Longitude"]
|
|
66
91
|
end
|
|
@@ -69,6 +94,13 @@ module USGeo
|
|
|
69
94
|
end
|
|
70
95
|
end
|
|
71
96
|
|
|
97
|
+
# Full name of the county with the state.
|
|
98
|
+
#
|
|
99
|
+
# @return [String]
|
|
100
|
+
def full_name
|
|
101
|
+
"#{name}, #{state_code}"
|
|
102
|
+
end
|
|
103
|
+
|
|
72
104
|
def state_fips
|
|
73
105
|
geoid[0, 2]
|
|
74
106
|
end
|
|
@@ -79,12 +111,31 @@ module USGeo
|
|
|
79
111
|
|
|
80
112
|
# Return the CBSA only if it is a metropolitan area.
|
|
81
113
|
def metropolitan_area
|
|
82
|
-
core_based_statistical_area if core_based_statistical_area
|
|
114
|
+
core_based_statistical_area if core_based_statistical_area&.metropolitan?
|
|
83
115
|
end
|
|
84
116
|
|
|
117
|
+
# Return a single time zone for the county. If the county has two time zones,
|
|
118
|
+
# only one is returned.
|
|
119
|
+
#
|
|
120
|
+
# @return [ActiveSupport::TimeZone, nil]
|
|
85
121
|
def time_zone
|
|
86
122
|
ActiveSupport::TimeZone[time_zone_name] if time_zone_name
|
|
87
123
|
end
|
|
88
124
|
|
|
125
|
+
# Get all time zones for the county.
|
|
126
|
+
#
|
|
127
|
+
# @return [Array<ActiveSupport::TimeZone>]
|
|
128
|
+
def time_zones
|
|
129
|
+
[time_zone_name, time_zone_2_name].compact.collect do |tz_name|
|
|
130
|
+
ActiveSupport::TimeZone[tz_name]
|
|
131
|
+
end.compact
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# True if the county is an outlying county in the CBSA.
|
|
135
|
+
#
|
|
136
|
+
# @return [Boolean]
|
|
137
|
+
def outlying?
|
|
138
|
+
!central?
|
|
139
|
+
end
|
|
89
140
|
end
|
|
90
141
|
end
|
|
@@ -1,24 +1,58 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module USGeo
|
|
4
|
-
|
|
5
4
|
# County subdivision.
|
|
6
5
|
class CountySubdivision < BaseRecord
|
|
7
|
-
|
|
8
|
-
include
|
|
6
|
+
include Population
|
|
7
|
+
include Area
|
|
9
8
|
|
|
10
9
|
self.primary_key = "geoid"
|
|
11
10
|
|
|
12
11
|
belongs_to :county, foreign_key: :county_geoid, inverse_of: :subdivisions
|
|
13
12
|
|
|
13
|
+
has_many :zcta_county_subdivisions, -> { not_removed }, foreign_key: :county_subdivision_geoid, inverse_of: :county_subdivision, dependent: :destroy
|
|
14
|
+
has_many :zctas, -> { not_removed }, through: :zcta_county_subdivisions
|
|
15
|
+
|
|
16
|
+
has_many :urban_area_county_subdivisions, foreign_key: :county_subdivision_geoid, inverse_of: :county_subdivision, dependent: :destroy
|
|
17
|
+
has_many :urban_areas, through: :urban_area_county_subdivisions
|
|
18
|
+
|
|
14
19
|
validates :geoid, length: {is: 10}
|
|
15
|
-
validates :name, length: {maximum: 60}
|
|
20
|
+
validates :name, presence: true, length: {maximum: 60}, uniqueness: {scope: :county_geoid}
|
|
16
21
|
validates :fips_class_code, length: {is: 2}
|
|
17
22
|
validates :land_area, numericality: true, allow_nil: true
|
|
18
23
|
validates :water_area, numericality: true, allow_nil: true
|
|
19
24
|
validates :population, numericality: {only_integer: true}, allow_nil: true
|
|
20
25
|
validates :housing_units, numericality: {only_integer: true}, allow_nil: true
|
|
21
26
|
|
|
27
|
+
# @!attribute geoid
|
|
28
|
+
# @return [String] 10-digit code for the subdivision.
|
|
29
|
+
|
|
30
|
+
# @!attribute name
|
|
31
|
+
# @return [String] Name of the subdivision.
|
|
32
|
+
|
|
33
|
+
# @!attribute fips_class_code
|
|
34
|
+
# @return [String] 2-character FIPS class code.
|
|
35
|
+
|
|
36
|
+
# @!method :core_based_statistical_area
|
|
37
|
+
# @return [CoreBasedStatisticalArea] Core-based statistical area the subdivision is in.
|
|
38
|
+
delegate :core_based_statistical_area, to: :county
|
|
39
|
+
|
|
40
|
+
# @!method :combined_statistical_area
|
|
41
|
+
# @return [CombinedStatisticalArea] Combined statistical area the subdivision is in.
|
|
42
|
+
delegate :combined_statistical_area, to: :county
|
|
43
|
+
|
|
44
|
+
# @!method :metropolitan_division
|
|
45
|
+
# @return [MetropolitanDivision] Metropolitan division the subdivision is in.
|
|
46
|
+
delegate :metropolitan_division, to: :county
|
|
47
|
+
|
|
48
|
+
# @!method :state
|
|
49
|
+
# @return [State] State the subdivision is in.
|
|
50
|
+
delegate :state, to: :county
|
|
51
|
+
|
|
52
|
+
# @!method :state_code
|
|
53
|
+
# @return [String] 2-character state code.
|
|
54
|
+
delegate :state_code, to: :county
|
|
55
|
+
|
|
22
56
|
class << self
|
|
23
57
|
def load!(uri = nil)
|
|
24
58
|
location = data_uri(uri || "county_subdivisions.csv")
|
|
@@ -32,15 +66,17 @@ module USGeo
|
|
|
32
66
|
record.fips_class_code = row["FIPS Class"]
|
|
33
67
|
record.population = row["Population"]
|
|
34
68
|
record.housing_units = row["Housing Units"]
|
|
35
|
-
record.land_area =
|
|
36
|
-
record.water_area =
|
|
69
|
+
record.land_area = row["Land Area"]
|
|
70
|
+
record.water_area = row["Water Area"]
|
|
37
71
|
record.lat = row["Latitude"]
|
|
38
72
|
record.lng = row["Longitude"]
|
|
73
|
+
|
|
74
|
+
duplicate = where.not(geoid: record.geoid).find_by(name: record.name, county_geoid: record.county_geoid)
|
|
75
|
+
duplicate&.update!(name: "#{record.name} (deleted)", status: BaseRecord::STATUS_REMOVED)
|
|
39
76
|
end
|
|
40
77
|
end
|
|
41
78
|
end
|
|
42
79
|
end
|
|
43
80
|
end
|
|
44
|
-
|
|
45
81
|
end
|
|
46
82
|
end
|
data/lib/us_geo/division.rb
CHANGED
|
@@ -1,29 +1,39 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module USGeo
|
|
4
|
-
|
|
5
4
|
# U.S. regional division composed of states.
|
|
6
5
|
class Division < BaseRecord
|
|
6
|
+
include Population
|
|
7
|
+
include Area
|
|
7
8
|
|
|
8
9
|
belongs_to :region, inverse_of: :divisions
|
|
9
|
-
has_many :states, inverse_of: :division
|
|
10
|
+
has_many :states, -> { not_removed }, inverse_of: :division
|
|
11
|
+
|
|
12
|
+
validates :name, presence: true, length: {maximum: 30}, uniqueness: true
|
|
13
|
+
|
|
14
|
+
# @!attribute id
|
|
15
|
+
# @return [Integer] ID of the division.
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
# @!attribute name
|
|
18
|
+
# @return [String] Name of the division.
|
|
12
19
|
|
|
13
20
|
class << self
|
|
14
21
|
def load!(uri = nil)
|
|
15
22
|
location = data_uri(uri || "divisions.csv")
|
|
16
|
-
|
|
23
|
+
|
|
17
24
|
import! do
|
|
18
25
|
load_data_file(location) do |row|
|
|
19
|
-
load_record!(id: row["
|
|
20
|
-
record.name = row["
|
|
26
|
+
load_record!(id: row["ID"]) do |record|
|
|
27
|
+
record.name = row["Name"]
|
|
21
28
|
record.region_id = row["Region ID"]
|
|
29
|
+
record.population = row["Population"]
|
|
30
|
+
record.housing_units = row["Housing Units"]
|
|
31
|
+
record.land_area = row["Land Area"]
|
|
32
|
+
record.water_area = row["Water Area"]
|
|
22
33
|
end
|
|
23
34
|
end
|
|
24
35
|
end
|
|
25
36
|
end
|
|
26
37
|
end
|
|
27
|
-
|
|
28
38
|
end
|
|
29
39
|
end
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module USGeo
|
|
4
|
-
|
|
5
4
|
# Core based statistical area with a population greater then 50,000.
|
|
6
5
|
class MetropolitanArea < CoreBasedStatisticalArea
|
|
7
|
-
|
|
8
6
|
def metropolitan?
|
|
9
7
|
true
|
|
10
8
|
end
|
|
11
|
-
|
|
9
|
+
|
|
12
10
|
def micropolitan?
|
|
13
11
|
false
|
|
14
12
|
end
|
|
15
|
-
|
|
16
13
|
end
|
|
17
|
-
|
|
18
14
|
end
|
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module USGeo
|
|
4
|
-
|
|
5
4
|
# Division of very large metropolitian areas into groups of approximately 2.5 million people.
|
|
6
5
|
class MetropolitanDivision < BaseRecord
|
|
7
|
-
|
|
8
|
-
include
|
|
6
|
+
include Population
|
|
7
|
+
include Area
|
|
9
8
|
|
|
10
9
|
self.primary_key = "geoid"
|
|
11
10
|
|
|
12
|
-
has_many :counties, foreign_key: :metropolitan_division_geoid, inverse_of: :metropolitan_division
|
|
11
|
+
has_many :counties, -> { not_removed }, foreign_key: :metropolitan_division_geoid, inverse_of: :metropolitan_division
|
|
13
12
|
belongs_to :core_based_statistical_area, foreign_key: :cbsa_geoid, optional: true, inverse_of: :metropolitan_divisions
|
|
14
13
|
|
|
15
14
|
validates :geoid, length: {is: 5}
|
|
16
|
-
validates :name, length: {maximum: 60}
|
|
15
|
+
validates :name, presence: true, length: {maximum: 60}, uniqueness: true
|
|
17
16
|
validates :land_area, numericality: true, presence: true
|
|
18
17
|
validates :water_area, numericality: true, presence: true
|
|
19
18
|
validates :population, numericality: {only_integer: true}, presence: true
|
|
20
|
-
validates :housing_units, numericality: {only_integer: true},
|
|
19
|
+
validates :housing_units, numericality: {only_integer: true}, presence: true
|
|
20
|
+
|
|
21
|
+
# @!attribute geoid
|
|
22
|
+
# @return [String] 5-digit code for the metropolitan division.
|
|
23
|
+
|
|
24
|
+
# @!attribute name
|
|
25
|
+
# @return [String] Name of the metropolitan division.
|
|
26
|
+
|
|
27
|
+
# @!method combined_statistical_area
|
|
28
|
+
# @return [CombinedStatisticalArea, nil] Combined statistical area that the metropolitan division is a part of.
|
|
29
|
+
delegate :combined_statistical_area, to: :core_based_statistical_area, allow_nil: true
|
|
21
30
|
|
|
22
31
|
class << self
|
|
23
32
|
def load!(uri = nil)
|
|
@@ -30,13 +39,12 @@ module USGeo
|
|
|
30
39
|
record.cbsa_geoid = row["CBSA"]
|
|
31
40
|
record.population = row["Population"]
|
|
32
41
|
record.housing_units = row["Housing Units"]
|
|
33
|
-
record.land_area =
|
|
34
|
-
record.water_area =
|
|
42
|
+
record.land_area = row["Land Area"]
|
|
43
|
+
record.water_area = row["Water Area"]
|
|
35
44
|
end
|
|
36
45
|
end
|
|
37
46
|
end
|
|
38
47
|
end
|
|
39
48
|
end
|
|
40
|
-
|
|
41
49
|
end
|
|
42
50
|
end
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module USGeo
|
|
4
|
-
|
|
5
4
|
# Core based statistical area with a population greater then 10,000 but less than 50,000.
|
|
6
5
|
class MicropolitanArea < CoreBasedStatisticalArea
|
|
7
|
-
|
|
8
6
|
def metropolitan?
|
|
9
7
|
false
|
|
10
8
|
end
|
|
11
|
-
|
|
9
|
+
|
|
12
10
|
def micropolitan?
|
|
13
11
|
true
|
|
14
12
|
end
|
|
15
|
-
|
|
16
13
|
end
|
|
17
|
-
|
|
18
14
|
end
|
data/lib/us_geo/place.rb
CHANGED
|
@@ -1,29 +1,46 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module USGeo
|
|
4
|
-
|
|
5
4
|
# Division of very large metropolitian areas into groups of approximately 2.5 million people.
|
|
6
5
|
class Place < BaseRecord
|
|
7
|
-
|
|
8
|
-
include
|
|
6
|
+
include Population
|
|
7
|
+
include Area
|
|
9
8
|
|
|
10
9
|
self.primary_key = "geoid"
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
# !@method zcta_places
|
|
12
|
+
# @return [ActiveRecord::Relation<ZctaPlace>] ZCTA to place mapping.
|
|
13
|
+
has_many :zcta_places, -> { not_removed }, foreign_key: :place_geoid, inverse_of: :place, dependent: :destroy
|
|
14
|
+
|
|
15
|
+
# !@method zctas
|
|
16
|
+
# @return [ActiveRecord::Relation<Zcta>] ZCTA's that overlap with this place.
|
|
17
|
+
has_many :zctas, -> { not_removed }, through: :zcta_places
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
# !@method place_counties
|
|
20
|
+
# @return [ActiveRecord::Relation<PlaceCounty>] Place to county mapping.
|
|
21
|
+
has_many :place_counties, -> { not_removed }, foreign_key: :place_geoid, inverse_of: :place, dependent: :destroy
|
|
17
22
|
|
|
23
|
+
# !@method counties
|
|
24
|
+
# @return [ActiveRecord::Relation<County>] Counties that this place is a part of.
|
|
25
|
+
has_many :counties, -> { not_removed }, through: :place_counties
|
|
26
|
+
|
|
27
|
+
# !@method primary_county
|
|
28
|
+
# @return [County] County that contains most of the place.
|
|
18
29
|
belongs_to :primary_county, foreign_key: :primary_county_geoid, class_name: "USGeo::County"
|
|
30
|
+
|
|
31
|
+
# !@method urban_area
|
|
32
|
+
# @return [UrbanArea] Urban area that the place is a part of.
|
|
19
33
|
belongs_to :urban_area, foreign_key: :urban_area_geoid, optional: true, class_name: "USGeo::UrbanArea"
|
|
34
|
+
|
|
35
|
+
# !@method state
|
|
36
|
+
# @return [State] State that the place is in.
|
|
20
37
|
belongs_to :state, foreign_key: :state_code, inverse_of: :places
|
|
21
38
|
|
|
22
39
|
validates :geoid, length: {is: 7}
|
|
23
40
|
validates :state_code, length: {is: 2}
|
|
24
41
|
validates :primary_county_geoid, length: {is: 5}
|
|
25
42
|
validates :urban_area_geoid, length: {is: 5}, allow_nil: true
|
|
26
|
-
validates :name, length: {maximum: 60}
|
|
43
|
+
validates :name, presence: true, length: {maximum: 60}
|
|
27
44
|
validates :short_name, length: {maximum: 30}
|
|
28
45
|
validates :fips_class_code, length: {is: 2}
|
|
29
46
|
validates :land_area, numericality: true, allow_nil: true
|
|
@@ -31,6 +48,40 @@ module USGeo
|
|
|
31
48
|
validates :population, numericality: {only_integer: true}, allow_nil: true
|
|
32
49
|
validates :housing_units, numericality: {only_integer: true}, allow_nil: true
|
|
33
50
|
|
|
51
|
+
# @!attribute geoid
|
|
52
|
+
# @return [String] 7-digit code for the place.
|
|
53
|
+
|
|
54
|
+
# @!attribute name
|
|
55
|
+
# @return [String] Name of the place.
|
|
56
|
+
|
|
57
|
+
# @!attribute short_name
|
|
58
|
+
# @return [String] Short name of the place.
|
|
59
|
+
|
|
60
|
+
# @!attribute state_code
|
|
61
|
+
# @return [String] 2-letter code for the state.
|
|
62
|
+
|
|
63
|
+
# @!attribute fips_class_code
|
|
64
|
+
# @return [String] 2-character FIPS class code.
|
|
65
|
+
|
|
66
|
+
# @!method combined_statistical_area
|
|
67
|
+
# @return [CombinedStatisticalArea, nil] Combined statistical area that the place is a part of.
|
|
68
|
+
delegate :combined_statistical_area, to: :primary_county, allow_nil: true
|
|
69
|
+
|
|
70
|
+
# @!method core_based_statistical_area
|
|
71
|
+
# @return [CoreBasedStatisticalArea, nil] Core-based statistical area that the place is a part of.
|
|
72
|
+
delegate :core_based_statistical_area, to: :primary_county, allow_nil: true
|
|
73
|
+
|
|
74
|
+
# @!method metropolitan_division
|
|
75
|
+
# @return [MetropolitanDivision, nil] Metropolitan division that the place is a part of.
|
|
76
|
+
delegate :metropolitan_division, to: :primary_county, allow_nil: true
|
|
77
|
+
|
|
78
|
+
# Full name of the place as short name plus the state.
|
|
79
|
+
#
|
|
80
|
+
# @return [String]
|
|
81
|
+
def full_name
|
|
82
|
+
"#{short_name}, #{state_code}"
|
|
83
|
+
end
|
|
84
|
+
|
|
34
85
|
class << self
|
|
35
86
|
def load!(uri = nil)
|
|
36
87
|
location = data_uri(uri || "places.csv")
|
|
@@ -47,8 +98,8 @@ module USGeo
|
|
|
47
98
|
record.fips_class_code = row["FIPS Class"]
|
|
48
99
|
record.population = row["Population"]
|
|
49
100
|
record.housing_units = row["Housing Units"]
|
|
50
|
-
record.land_area =
|
|
51
|
-
record.water_area =
|
|
101
|
+
record.land_area = row["Land Area"]
|
|
102
|
+
record.water_area = row["Water Area"]
|
|
52
103
|
record.lat = row["Latitude"]
|
|
53
104
|
record.lng = row["Longitude"]
|
|
54
105
|
end
|
|
@@ -56,6 +107,5 @@ module USGeo
|
|
|
56
107
|
end
|
|
57
108
|
end
|
|
58
109
|
end
|
|
59
|
-
|
|
60
110
|
end
|
|
61
111
|
end
|
data/lib/us_geo/place_county.rb
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module USGeo
|
|
4
|
-
|
|
5
|
-
# Mapping of urban areas to counties they overlap with.
|
|
4
|
+
# Mapping of places to counties they overlap with.
|
|
6
5
|
class PlaceCounty < BaseRecord
|
|
7
|
-
|
|
8
6
|
belongs_to :county, foreign_key: :county_geoid, inverse_of: :place_counties
|
|
9
7
|
belongs_to :place, foreign_key: :place_geoid, inverse_of: :place_counties
|
|
10
8
|
|
|
@@ -23,6 +21,5 @@ module USGeo
|
|
|
23
21
|
end
|
|
24
22
|
end
|
|
25
23
|
end
|
|
26
|
-
|
|
27
24
|
end
|
|
28
25
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module USGeo
|
|
4
|
+
# This module is mixed into all models with a population and land area.
|
|
5
|
+
module Population
|
|
6
|
+
# @!attribute population
|
|
7
|
+
# @return [Integer, nil] Total population of the area.
|
|
8
|
+
|
|
9
|
+
# @!attribute housing_units
|
|
10
|
+
# @return [Integer, nil] Total housing units in the area.
|
|
11
|
+
|
|
12
|
+
# Population per square mile.
|
|
13
|
+
#
|
|
14
|
+
# @return [Float, nil]
|
|
15
|
+
def population_density
|
|
16
|
+
population.to_f / land_area if population && land_area.to_f > 0
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Population per square kilometer.
|
|
20
|
+
#
|
|
21
|
+
# @return [Float, nil]
|
|
22
|
+
def population_density_km
|
|
23
|
+
population.to_f / land_area_km if population && land_area.to_f > 0
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/us_geo/region.rb
CHANGED
|
@@ -1,28 +1,38 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module USGeo
|
|
4
|
-
|
|
5
4
|
# U.S. region.
|
|
6
5
|
class Region < BaseRecord
|
|
6
|
+
include Population
|
|
7
|
+
include Area
|
|
8
|
+
|
|
9
|
+
has_many :divisions, -> { not_removed }, inverse_of: :region
|
|
10
|
+
has_many :states, -> { not_removed }, inverse_of: :region
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
has_many :states, inverse_of: :region
|
|
12
|
+
validates :name, presence: true, length: {maximum: 30}, uniqueness: true
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
# @!attribute id
|
|
15
|
+
# @return [Integer] ID of the region.
|
|
16
|
+
|
|
17
|
+
# @!attribute name
|
|
18
|
+
# @return [String] Name of the region.
|
|
12
19
|
|
|
13
20
|
class << self
|
|
14
21
|
def load!(uri = nil)
|
|
15
|
-
location = data_uri(uri || "
|
|
22
|
+
location = data_uri(uri || "regions.csv")
|
|
16
23
|
|
|
17
24
|
import! do
|
|
18
25
|
load_data_file(location) do |row|
|
|
19
|
-
load_record!(id: row["
|
|
20
|
-
record.name = row["
|
|
26
|
+
load_record!(id: row["ID"]) do |record|
|
|
27
|
+
record.name = row["Name"]
|
|
28
|
+
record.population = row["Population"]
|
|
29
|
+
record.housing_units = row["Housing Units"]
|
|
30
|
+
record.land_area = row["Land Area"]
|
|
31
|
+
record.water_area = row["Water Area"]
|
|
21
32
|
end
|
|
22
33
|
end
|
|
23
34
|
end
|
|
24
35
|
end
|
|
25
36
|
end
|
|
26
|
-
|
|
27
37
|
end
|
|
28
38
|
end
|
data/lib/us_geo/state.rb
CHANGED
|
@@ -1,31 +1,49 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module USGeo
|
|
4
|
-
|
|
5
4
|
# U.S. state or territory.
|
|
6
5
|
class State < BaseRecord
|
|
6
|
+
include Population
|
|
7
|
+
include Area
|
|
7
8
|
|
|
8
9
|
STATE_TYPE = "state"
|
|
9
10
|
DISTRICT_TYPE = "district"
|
|
10
11
|
TERRITORY_TYPE = "territory"
|
|
11
|
-
|
|
12
|
+
|
|
12
13
|
self.primary_key = "code"
|
|
13
14
|
self.inheritance_column = :_type_disabled
|
|
14
15
|
|
|
15
16
|
belongs_to :region, optional: -> { territory? }, inverse_of: :states
|
|
16
17
|
belongs_to :division, optional: -> { territory? }, inverse_of: :states
|
|
17
|
-
has_many :counties, foreign_key: :state_code, inverse_of: :state
|
|
18
|
-
has_many :places, foreign_key: :state_code, inverse_of: :state
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
has_many :counties, -> { not_removed }, foreign_key: :state_code, inverse_of: :state
|
|
20
|
+
has_many :places, -> { not_removed }, foreign_key: :state_code, inverse_of: :state
|
|
21
|
+
|
|
22
|
+
validates :code, length: {is: 2}, uniqueness: true
|
|
21
23
|
validates :fips, length: {is: 2}
|
|
22
|
-
validates :name, length: {maximum: 30}
|
|
24
|
+
validates :name, presence: true, length: {maximum: 30}, uniqueness: true
|
|
23
25
|
validates :type, inclusion: [STATE_TYPE, DISTRICT_TYPE, TERRITORY_TYPE]
|
|
24
26
|
|
|
27
|
+
# @!attribute code
|
|
28
|
+
# @return [String] 2-letter postal code of the state.
|
|
29
|
+
|
|
30
|
+
# @!attribute name
|
|
31
|
+
# @return [String] Name of the state.
|
|
32
|
+
|
|
33
|
+
# @!attribute fips
|
|
34
|
+
# @return [String] 2-digit FIPS code of the state.
|
|
35
|
+
|
|
36
|
+
# @!attribute type
|
|
37
|
+
# @return [String] Type of the state or territory.
|
|
38
|
+
|
|
39
|
+
# @!method :region
|
|
40
|
+
# @return [Region] Region the state is in.
|
|
41
|
+
delegate :region, to: :division, allow_nil: true
|
|
42
|
+
|
|
25
43
|
class << self
|
|
26
44
|
def load!(uri = nil)
|
|
27
45
|
location = data_uri(uri || "states.csv")
|
|
28
|
-
|
|
46
|
+
|
|
29
47
|
import! do
|
|
30
48
|
load_data_file(location) do |row|
|
|
31
49
|
load_record!(code: row["Code"]) do |record|
|
|
@@ -34,23 +52,26 @@ module USGeo
|
|
|
34
52
|
record.fips = row["FIPS"]
|
|
35
53
|
record.region_id = row["Region ID"]
|
|
36
54
|
record.division_id = row["Division ID"]
|
|
55
|
+
record.population = row["Population"]
|
|
56
|
+
record.housing_units = row["Housing Units"]
|
|
57
|
+
record.land_area = row["Land Area"]
|
|
58
|
+
record.water_area = row["Water Area"]
|
|
37
59
|
end
|
|
38
60
|
end
|
|
39
61
|
end
|
|
40
62
|
end
|
|
41
63
|
end
|
|
42
|
-
|
|
64
|
+
|
|
43
65
|
def state?
|
|
44
66
|
type == STATE_TYPE
|
|
45
67
|
end
|
|
46
|
-
|
|
68
|
+
|
|
47
69
|
def territory?
|
|
48
70
|
type == TERRITORY_TYPE
|
|
49
71
|
end
|
|
50
|
-
|
|
72
|
+
|
|
51
73
|
def district?
|
|
52
74
|
type == DISTRICT_TYPE
|
|
53
75
|
end
|
|
54
|
-
|
|
55
76
|
end
|
|
56
77
|
end
|