us_geo 1.0.2 → 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.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -0
  3. data/MIT_LICENSE.txt +21 -0
  4. data/README.md +77 -60
  5. data/UPDATING_TO_VERSION_2.md +172 -0
  6. data/VERSION +1 -0
  7. data/db/migrate/20190221054200_create_regions.rb +4 -2
  8. data/db/migrate/20190221054300_create_divisions.rb +4 -2
  9. data/db/migrate/20190221054400_create_states.rb +4 -2
  10. data/db/migrate/20190221054500_create_combined_statistical_areas.rb +4 -2
  11. data/db/migrate/20190221054600_create_core_based_statistical_areas.rb +4 -2
  12. data/db/migrate/20190221054650_create_metropolitan_divisions.rb +4 -2
  13. data/db/migrate/20190221054700_create_counties.rb +4 -3
  14. data/db/migrate/20190221054800_create_zctas.rb +4 -2
  15. data/db/migrate/20190221054900_create_zcta_counties.rb +4 -2
  16. data/db/migrate/20190221055000_create_urban_areas.rb +4 -2
  17. data/db/migrate/20190221055100_create_urban_area_counties.rb +4 -4
  18. data/db/migrate/20190221055200_create_zcta_urban_areas.rb +4 -4
  19. data/db/migrate/20190221060000_create_places.rb +4 -2
  20. data/db/migrate/20190221061000_create_place_counties.rb +4 -2
  21. data/db/migrate/20190221062000_create_zcta_places.rb +4 -4
  22. data/db/migrate/20190221063000_create_county_subdivisions.rb +4 -2
  23. data/db/migrate/20220722000000_allow_null_zcta_counties_demographics.rb +23 -0
  24. data/db/migrate/20220722000200_allow_null_zcta_places_demographics.rb +23 -0
  25. data/db/migrate/20230414000000_add_zcta_primary_place.rb +13 -0
  26. data/db/migrate/20230414000200_add_demographics_to_regions.rb +28 -0
  27. data/db/migrate/20230414000300_add_demographics_to_divisions.rb +28 -0
  28. data/db/migrate/20230414000400_add_demographics_to_states.rb +28 -0
  29. data/db/migrate/20230414000700_add_short_name_to_core_based_statistical_areas.rb +22 -0
  30. data/db/migrate/20230414000750_add_short_name_to_combined_statistical_areas.rb +22 -0
  31. data/db/migrate/20230414000800_create_zcta_mappings.rb +18 -0
  32. data/db/migrate/20230417000100_create_zcta_county_subdivisions.rb +22 -0
  33. data/db/migrate/20230417000200_add_unique_name_index_to_county_subdivisions.rb +26 -0
  34. data/db/migrate/20230417000250_add_zcta_primary_county_subdivision.rb +13 -0
  35. data/db/migrate/20230417000300_create_urban_area_county_subdivisions.rb +23 -0
  36. data/db/migrate/20230417000400_allow_null_urban_area_counties_demographics.rb +23 -0
  37. data/db/migrate/20230417000500_allow_null_zcta_urban_areas_demographics.rb +23 -0
  38. data/db/migrate/20230417000600_add_additional_time_zone_name_to_counties.rb +13 -0
  39. data/db/schema.rb +303 -0
  40. data/explorer_app/.gitattributes +7 -0
  41. data/explorer_app/.gitignore +34 -0
  42. data/explorer_app/Gemfile +38 -0
  43. data/explorer_app/Rakefile +6 -0
  44. data/explorer_app/app/assets/images/.keep +0 -0
  45. data/explorer_app/app/assets/stylesheets/application.css +1 -0
  46. data/explorer_app/app/controllers/application_controller.rb +64 -0
  47. data/explorer_app/app/controllers/combined_statistical_areas_controller.rb +12 -0
  48. data/explorer_app/app/controllers/concerns/.keep +0 -0
  49. data/explorer_app/app/controllers/core_based_statistical_areas_controller.rb +36 -0
  50. data/explorer_app/app/controllers/counties_controller.rb +22 -0
  51. data/explorer_app/app/controllers/county_subdivisions_controller.rb +23 -0
  52. data/explorer_app/app/controllers/divisions_controller.rb +27 -0
  53. data/explorer_app/app/controllers/home_controller.rb +6 -0
  54. data/explorer_app/app/controllers/metropolitan_divisions_controller.rb +27 -0
  55. data/explorer_app/app/controllers/places_controller.rb +23 -0
  56. data/explorer_app/app/controllers/regions_controller.rb +13 -0
  57. data/explorer_app/app/controllers/states_controller.rb +25 -0
  58. data/explorer_app/app/controllers/urban_areas_controller.rb +24 -0
  59. data/explorer_app/app/controllers/zctas_controller.rb +23 -0
  60. data/explorer_app/app/helpers/application_helper.rb +137 -0
  61. data/explorer_app/app/models/application_record.rb +3 -0
  62. data/explorer_app/app/models/concerns/.keep +0 -0
  63. data/explorer_app/app/views/combined_statistical_areas/_table.html.erb +18 -0
  64. data/explorer_app/app/views/combined_statistical_areas/index.html.erb +7 -0
  65. data/explorer_app/app/views/combined_statistical_areas/show.html.erb +52 -0
  66. data/explorer_app/app/views/core_based_statistical_areas/_table.html.erb +32 -0
  67. data/explorer_app/app/views/core_based_statistical_areas/index.html.erb +19 -0
  68. data/explorer_app/app/views/core_based_statistical_areas/show.html.erb +60 -0
  69. data/explorer_app/app/views/counties/_table.html.erb +64 -0
  70. data/explorer_app/app/views/counties/show.html.erb +96 -0
  71. data/explorer_app/app/views/county_subdivisions/_table.html.erb +48 -0
  72. data/explorer_app/app/views/county_subdivisions/show.html.erb +84 -0
  73. data/explorer_app/app/views/divisions/_table.html.erb +24 -0
  74. data/explorer_app/app/views/divisions/index.html.erb +3 -0
  75. data/explorer_app/app/views/divisions/show.html.erb +3 -0
  76. data/explorer_app/app/views/home/index.html.erb +23 -0
  77. data/explorer_app/app/views/layouts/application.html.erb +34 -0
  78. data/explorer_app/app/views/metropolitan_divisions/_table.html.erb +42 -0
  79. data/explorer_app/app/views/metropolitan_divisions/index.html.erb +8 -0
  80. data/explorer_app/app/views/metropolitan_divisions/show.html.erb +46 -0
  81. data/explorer_app/app/views/places/_table.html.erb +47 -0
  82. data/explorer_app/app/views/places/show.html.erb +92 -0
  83. data/explorer_app/app/views/regions/_table.html.erb +18 -0
  84. data/explorer_app/app/views/regions/index.html.erb +7 -0
  85. data/explorer_app/app/views/regions/show.html.erb +3 -0
  86. data/explorer_app/app/views/shared/_breadcrumbs.html.erb +13 -0
  87. data/explorer_app/app/views/shared/_demographics_cells.html.erb +5 -0
  88. data/explorer_app/app/views/shared/_demographics_headers.html.erb +5 -0
  89. data/explorer_app/app/views/states/_table.html.erb +31 -0
  90. data/explorer_app/app/views/states/index.html.erb +7 -0
  91. data/explorer_app/app/views/states/show.html.erb +54 -0
  92. data/explorer_app/app/views/urban_areas/_table.html.erb +45 -0
  93. data/explorer_app/app/views/urban_areas/index.html.erb +19 -0
  94. data/explorer_app/app/views/urban_areas/show.html.erb +68 -0
  95. data/explorer_app/app/views/zctas/_table.html.erb +60 -0
  96. data/explorer_app/app/views/zctas/show.html.erb +104 -0
  97. data/explorer_app/bin/bundle +109 -0
  98. data/explorer_app/bin/rails +4 -0
  99. data/explorer_app/bin/rake +4 -0
  100. data/explorer_app/bin/setup +33 -0
  101. data/explorer_app/config/application.rb +37 -0
  102. data/explorer_app/config/boot.rb +3 -0
  103. data/explorer_app/config/database.yml +13 -0
  104. data/explorer_app/config/environment.rb +5 -0
  105. data/explorer_app/config/environments/development.rb +59 -0
  106. data/explorer_app/config/initializers/filter_parameter_logging.rb +8 -0
  107. data/explorer_app/config/locales/en.yml +2 -0
  108. data/explorer_app/config/puma.rb +43 -0
  109. data/explorer_app/config/routes.rb +56 -0
  110. data/explorer_app/config.ru +6 -0
  111. data/explorer_app/db/seeds.rb +7 -0
  112. data/explorer_app/lib/assets/.keep +0 -0
  113. data/explorer_app/lib/tasks/.keep +0 -0
  114. data/explorer_app/log/.keep +0 -0
  115. data/explorer_app/public/404.html +67 -0
  116. data/explorer_app/public/422.html +67 -0
  117. data/explorer_app/public/500.html +66 -0
  118. data/explorer_app/public/apple-touch-icon-precomposed.png +0 -0
  119. data/explorer_app/public/apple-touch-icon.png +0 -0
  120. data/explorer_app/public/favicon.ico +0 -0
  121. data/explorer_app/public/robots.txt +1 -0
  122. data/explorer_app/tmp/.keep +0 -0
  123. data/explorer_app/tmp/pids/.keep +0 -0
  124. data/lib/tasks/us_geo/us_geo.rake +44 -3
  125. data/lib/us_geo/area.rb +44 -0
  126. data/lib/us_geo/base_record.rb +22 -16
  127. data/lib/us_geo/combined_statistical_area.rb +18 -8
  128. data/lib/us_geo/core_based_statistical_area.rb +24 -12
  129. data/lib/us_geo/county.rb +67 -16
  130. data/lib/us_geo/county_subdivision.rb +43 -7
  131. data/lib/us_geo/division.rb +17 -7
  132. data/lib/us_geo/metropolitan_area.rb +1 -5
  133. data/lib/us_geo/metropolitan_division.rb +17 -9
  134. data/lib/us_geo/micropolitan_area.rb +1 -5
  135. data/lib/us_geo/place.rb +61 -11
  136. data/lib/us_geo/place_county.rb +1 -4
  137. data/lib/us_geo/population.rb +26 -0
  138. data/lib/us_geo/region.rb +18 -8
  139. data/lib/us_geo/state.rb +32 -11
  140. data/lib/us_geo/urban_area.rb +46 -16
  141. data/lib/us_geo/urban_area_county.rb +4 -21
  142. data/lib/us_geo/urban_area_county_subdivision.rb +51 -0
  143. data/lib/us_geo/urban_cluster.rb +1 -5
  144. data/lib/us_geo/urbanized_area.rb +1 -5
  145. data/lib/us_geo/version.rb +1 -1
  146. data/lib/us_geo/zcta.rb +90 -13
  147. data/lib/us_geo/zcta_county.rb +5 -22
  148. data/lib/us_geo/zcta_county_subdivision.rb +51 -0
  149. data/lib/us_geo/zcta_mapping.rb +35 -0
  150. data/lib/us_geo/zcta_place.rb +5 -12
  151. data/lib/us_geo/zcta_urban_area.rb +3 -20
  152. data/lib/us_geo.rb +34 -31
  153. data/us_geo.gemspec +36 -0
  154. metadata +127 -132
  155. data/Gemfile +0 -5
  156. data/Gemfile.lock +0 -75
  157. data/Rakefile +0 -18
  158. data/db/migrate/20190221054490_create_designated_market_areas.rb +0 -16
  159. data/lib/us_geo/demographics.rb +0 -25
  160. data/lib/us_geo/designated_market_area.rb +0 -30
  161. data/spec/spec_helper.rb +0 -22
  162. data/spec/us_geo/base_record_spec.rb +0 -67
  163. data/spec/us_geo/combined_statistical_area_spec.rb +0 -33
  164. data/spec/us_geo/core_based_statistical_area_spec.rb +0 -56
  165. data/spec/us_geo/county_spec.rb +0 -131
  166. data/spec/us_geo/county_subdivision_spec.rb +0 -37
  167. data/spec/us_geo/demographics_spec.rb +0 -19
  168. data/spec/us_geo/designated_market_area_spec.rb +0 -29
  169. data/spec/us_geo/division_spec.rb +0 -37
  170. data/spec/us_geo/metropolitan_division_spec.rb +0 -41
  171. data/spec/us_geo/place_county_spec.rb +0 -39
  172. data/spec/us_geo/place_spec.rb +0 -71
  173. data/spec/us_geo/region_spec.rb +0 -36
  174. data/spec/us_geo/state_spec.rb +0 -70
  175. data/spec/us_geo/urban_area_county_spec.rb +0 -82
  176. data/spec/us_geo/urban_area_spec.rb +0 -98
  177. data/spec/us_geo/zcta_county_spec.rb +0 -82
  178. data/spec/us_geo/zcta_place_spec.rb +0 -82
  179. data/spec/us_geo/zcta_spec.rb +0 -99
  180. data/spec/us_geo/zcta_urban_area_spec.rb +0 -82
@@ -1,22 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module USGeo
4
-
5
4
  # Urban areas are split into either urbanized areas (population > 50,000) or urban cluster (population < 50,000).
6
5
  class UrbanArea < BaseRecord
7
-
8
- include Demographics
6
+ include Area
7
+ include Population
9
8
 
10
9
  self.primary_key = "geoid"
11
10
  self.store_full_sti_class = false
12
11
 
12
+ # !@method urban_area_counties
13
+ # @return [ActiveRecord::Relation<USGeo::UrbanAreaCounty>] County to urban area mapping.
13
14
  has_many :urban_area_counties, foreign_key: :urban_area_geoid, inverse_of: :urban_area, dependent: :destroy
15
+
16
+ # !@method counties
17
+ # @return [ActiveRecord::Relation<USGeo::County>] Counties that overlap with the urban area.
14
18
  has_many :counties, through: :urban_area_counties
19
+
20
+ # !@method primary_county
21
+ # @return [USGeo::County] Primary county that contains most of the urban area.
15
22
  belongs_to :primary_county, foreign_key: :primary_county_geoid, class_name: "USGeo::County"
16
-
23
+
24
+ # !@method urban_area_county_subdivisions
25
+ # @return [ActiveRecord::Relation<USGeo::UrbanAreaCountySubdivision>] County subdivision to urban area mapping.
26
+ has_many :urban_area_county_subdivisions, foreign_key: :urban_area_geoid, inverse_of: :urban_area, dependent: :destroy
27
+
28
+ # !@method county_subdivisions
29
+ # @return [ActiveRecord::Relation<USGeo::CountySubdivision>] County subdivisions that overlap with the urban area.
30
+ has_many :county_subdivisions, through: :urban_area_county_subdivisions
31
+
32
+ # !@method zcta_urban_areas
33
+ # @return [ActiveRecord::Relation<USGeo::ZctaUrbanArea>] Zip code to urban area mapping.
17
34
  has_many :zcta_urban_areas, foreign_key: :urban_area_geoid, inverse_of: :urban_area, dependent: :destroy
35
+
36
+ # !@method zctas
37
+ # @return [ActiveRecord::Relation<USGeo::Zcta>] Zip codes that overlap with the urban area.
18
38
  has_many :zctas, through: :zcta_urban_areas
19
39
 
40
+ # !@method places
41
+ # @return [ActiveRecord::Relation<USGeo::Place>] Places that overlap with the urban area.
42
+ has_many :places, foreign_key: :urban_area_geoid, inverse_of: :urban_area
43
+
20
44
  validates :geoid, length: {is: 5}
21
45
  validates :primary_county_geoid, length: {is: 5}
22
46
  validates :name, length: {maximum: 90}
@@ -26,26 +50,33 @@ module USGeo
26
50
  validates :population, numericality: {only_integer: true}, presence: true
27
51
  validates :housing_units, numericality: {only_integer: true}, presence: true
28
52
 
29
- delegate :core_based_statistical_area, :designated_market_area, :state, :state_code, :time_zone, to: :primary_county, allow_nil: true
53
+ # !@method combined_statistical_area
54
+ # @return [USGeo::CombinedStatisticalArea, nil] Combined statistical area that the urban area is a part of.
55
+ delegate :combined_statistical_area, to: :primary_county, allow_nil: true
56
+
57
+ # !@method core_based_statistical_area
58
+ # @return [USGeo::CoreBasedStatisticalArea, nil] Core-based statistical area that the urban area is a part of.
59
+ delegate :core_based_statistical_area, to: :primary_county, allow_nil: true
60
+
61
+ # !@method metropolitan_division
62
+ # @return [USGeo::MetropolitanDivision, nil] Metropolitan division that the urban area is a part of.
63
+ delegate :metropolitan_division, to: :primary_county, allow_nil: true
30
64
 
31
- before_save do
32
- self.short_name = name.sub(" Urbanized Area", "").sub(" Urban Cluster", "") if name
33
- end
34
-
35
65
  class << self
36
66
  def load!(uri = nil)
37
67
  location = data_uri(uri || "urban_areas.csv")
38
-
68
+
39
69
  import! do
40
70
  load_data_file(location) do |row|
41
71
  load_record!(geoid: row["GEOID"]) do |record|
42
- record.type = (row["Population"].to_i >= 50_000 ? "UrbanizedArea" : "UrbanCluster")
72
+ record.type = ((row["Population"].to_i >= 50_000) ? "UrbanizedArea" : "UrbanCluster")
43
73
  record.name = row["Name"]
44
- record.primary_county_geoid = row["Primary County"]
74
+ record.short_name = row["Short Name"]
75
+ record.primary_county_geoid = row["Primary County GEOID"]
45
76
  record.population = row["Population"]
46
77
  record.housing_units = row["Housing Units"]
47
- record.land_area = area_meters_to_miles(row["Land Area"])
48
- record.water_area = area_meters_to_miles(row["Water Area"])
78
+ record.land_area = row["Land Area"]
79
+ record.water_area = row["Water Area"]
49
80
  record.lat = row["Latitude"]
50
81
  record.lng = row["Longitude"]
51
82
  end
@@ -57,10 +88,9 @@ module USGeo
57
88
  def urbanized?
58
89
  raise NotImplementedError
59
90
  end
60
-
91
+
61
92
  def cluster?
62
93
  raise NotImplementedError
63
94
  end
64
-
65
95
  end
66
96
  end
@@ -1,11 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module USGeo
4
-
5
4
  # Mapping of urban areas to counties they overlap with.
6
5
  class UrbanAreaCounty < BaseRecord
7
-
8
- include Demographics
6
+ include Area
9
7
 
10
8
  belongs_to :county, foreign_key: :county_geoid, inverse_of: :urban_area_counties
11
9
  belongs_to :urban_area, foreign_key: :urban_area_geoid, inverse_of: :urban_area_counties
@@ -14,31 +12,22 @@ module USGeo
14
12
  validates :urban_area_geoid, length: {is: 5}
15
13
  validates :land_area, numericality: true, presence: true
16
14
  validates :water_area, numericality: true, presence: true
17
- validates :population, numericality: {only_integer: true}, presence: true
18
- validates :housing_units, numericality: {only_integer: true}, presence: true
19
15
 
20
16
  class << self
21
17
  def load!(uri = nil)
22
18
  location = data_uri(uri || "urban_area_counties.csv")
23
-
19
+
24
20
  import! do
25
21
  load_data_file(location) do |row|
26
22
  load_record!(urban_area_geoid: row["Urban Area GEOID"], county_geoid: row["County GEOID"]) do |record|
27
- record.population = row["Population"]
28
- record.housing_units = row["Housing Units"]
29
- record.land_area = area_meters_to_miles(row["Land Area"])
30
- record.water_area = area_meters_to_miles(row["Water Area"])
23
+ record.land_area = row["Land Area"]
24
+ record.water_area = row["Water Area"]
31
25
  end
32
26
  end
33
27
  end
34
28
  end
35
29
  end
36
30
 
37
- # Percentage of the urban area population.
38
- def percent_urban_area_population
39
- population.to_f / urban_area.population.to_f
40
- end
41
-
42
31
  # Percentage of the urban area land area.
43
32
  def percent_urban_area_land_area
44
33
  land_area / urban_area.land_area
@@ -49,11 +38,6 @@ module USGeo
49
38
  total_area / urban_area.total_area
50
39
  end
51
40
 
52
- # Percentage of the county population.
53
- def percent_county_population
54
- population.to_f / county.population.to_f
55
- end
56
-
57
41
  # Percentage of the county land area.
58
42
  def percent_county_land_area
59
43
  land_area / county.land_area
@@ -63,6 +47,5 @@ module USGeo
63
47
  def percent_county_total_area
64
48
  total_area / county.total_area
65
49
  end
66
-
67
50
  end
68
51
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module USGeo
4
+ # Mapping of urban areas to counties they overlap with.
5
+ class UrbanAreaCountySubdivision < BaseRecord
6
+ include Area
7
+
8
+ belongs_to :county_subdivision, foreign_key: :county_subdivision_geoid, inverse_of: :urban_area_county_subdivisions
9
+ belongs_to :urban_area, foreign_key: :urban_area_geoid, inverse_of: :urban_area_county_subdivisions
10
+
11
+ validates :county_subdivision_geoid, length: {is: 10}
12
+ validates :urban_area_geoid, length: {is: 5}
13
+ validates :land_area, numericality: true, presence: true
14
+ validates :water_area, numericality: true, presence: true
15
+
16
+ class << self
17
+ def load!(uri = nil)
18
+ location = data_uri(uri || "urban_area_county_subdivisions.csv")
19
+
20
+ import! do
21
+ load_data_file(location) do |row|
22
+ load_record!(urban_area_geoid: row["Urban Area GEOID"], county_subdivision_geoid: row["County Subdivision GEOID"]) do |record|
23
+ record.land_area = row["Land Area"]
24
+ record.water_area = row["Water Area"]
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ # Percentage of the urban area land area.
32
+ def percent_urban_area_land_area
33
+ land_area / urban_area.land_area
34
+ end
35
+
36
+ # Percentage of the urban area total area.
37
+ def percent_urban_area_total_area
38
+ total_area / urban_area.total_area
39
+ end
40
+
41
+ # Percentage of the county land area.
42
+ def percent_county_subdivision_land_area
43
+ land_area / county_subdivision.land_area
44
+ end
45
+
46
+ # Percentage of the county total area.
47
+ def percent_county_subdivision_total_area
48
+ total_area / county_subdivision.total_area
49
+ end
50
+ end
51
+ end
@@ -1,18 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module USGeo
4
-
5
4
  # Urban area with population < 50,000.
6
5
  class UrbanCluster < UrbanArea
7
-
8
6
  def urbanized?
9
7
  false
10
8
  end
11
-
9
+
12
10
  def cluster?
13
11
  true
14
12
  end
15
-
16
13
  end
17
-
18
14
  end
@@ -1,18 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module USGeo
4
-
5
4
  # Urban area with population >= 50,000.
6
5
  class UrbanizedArea < UrbanArea
7
-
8
6
  def urbanized?
9
7
  true
10
8
  end
11
-
9
+
12
10
  def cluster?
13
11
  false
14
12
  end
15
-
16
13
  end
17
-
18
14
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module USGeo
4
- VERSION = "1.0.2"
4
+ VERSION = File.read(File.expand_path("../../VERSION", __dir__)).chomp.freeze
5
5
  end
data/lib/us_geo/zcta.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module USGeo
4
-
5
4
  # ZIP code tabulation area. These roughly map to U.S. Postal service ZIP codes, but
6
5
  # are designed for geographic and demographic purposes instead of mail routing. In particular
7
6
  # certain optimizations that the Postal Service makes to optimize mail routing are
@@ -10,25 +9,74 @@ module USGeo
10
9
  # ZCTA's can span counties, but the one with the majority of the residents is identified
11
10
  # as the primary county for when a single county is required.
12
11
  #
13
- # ZCTA's can span urbanized area, but the one with the majority of the residents is identified
14
- # as the primary urbanized area for when a single area is required.
12
+ # ZCTA's can span places, but the one with the majority of the residents is identified
13
+ # as the primary place for when a single area is required.
15
14
  class Zcta < BaseRecord
16
-
17
- include Demographics
15
+ include Population
16
+ include Area
18
17
 
19
18
  self.table_name = "us_geo_zctas"
20
19
  self.primary_key = "zipcode"
21
20
 
22
- has_many :zcta_counties, foreign_key: :zipcode, inverse_of: :zcta, dependent: :destroy
23
- has_many :counties, through: :zcta_counties
21
+ # @!method self.for_zipcode
22
+ # This scope will search for ZCTA's via the ZCTAMappings table. This is useful
23
+ # when you have a retired ZIP code and want to find the current ZCTA for that ZIP code.
24
+ #
25
+ # @param zipcode [String] ZIP code to search for.
26
+ # @return [ActiveRecord::Relation] ZCTA's matching the given ZIP code.
27
+ scope :for_zipcode, ->(zipcode) { left_outer_joins(:zcta_mappings).where(ZctaMapping.table_name => {zipcode: zipcode}).or(left_outer_joins(:zcta_mappings).where(zipcode: zipcode)).distinct }
28
+
29
+ # @!method zcta_counties
30
+ # @return [ActiveRecord::Relation] ZCTA to county mappings.
31
+ has_many :zcta_counties, -> { not_removed }, foreign_key: :zipcode, inverse_of: :zcta, dependent: :destroy
32
+
33
+ # @!method counties
34
+ # @return [ActiveRecord::Relation] Counties that this ZCTA is a part of.
35
+ has_many :counties, -> { not_removed }, through: :zcta_counties
36
+
37
+ # @!method primary_county
38
+ # @return [USGeo::County] County that contains most of the ZCTA's land area.
24
39
  belongs_to :primary_county, foreign_key: :primary_county_geoid, class_name: "USGeo::County"
25
40
 
41
+ # @!method zcta_urban_areas
42
+ # @return [ActiveRecord::Relation] ZCTA to urban area mappings.
26
43
  has_many :zcta_urban_areas, foreign_key: :zipcode, inverse_of: :zcta, dependent: :destroy
44
+
45
+ # @!method urban_areas
46
+ # @return [ActiveRecord::Relation] Urban areas that this ZCTA is a part of.
27
47
  has_many :urban_areas, through: :zcta_urban_areas
48
+
49
+ # @!method primary_urban_area
50
+ # @return [USGeo::UrbanArea] Urban area that contains most of the ZCTA's land area.
28
51
  belongs_to :primary_urban_area, foreign_key: :primary_urban_area_geoid, class_name: "USGeo::UrbanArea"
29
52
 
30
- has_many :zcta_places, foreign_key: :zipcode, inverse_of: :zcta, dependent: :destroy
31
- has_many :places, through: :zcta_places
53
+ # @!method zcta_county_subdivisions
54
+ # @return [ActiveRecord::Relation] ZCTA to county subdivision mappings.
55
+ has_many :zcta_county_subdivisions, -> { not_removed }, foreign_key: :zipcode, inverse_of: :zcta, dependent: :destroy
56
+
57
+ # @!method county_subdivisions
58
+ # @return [ActiveRecord::Relation] County subdivisions that this ZCTA is a part of.
59
+ has_many :county_subdivisions, -> { not_removed }, through: :zcta_county_subdivisions
60
+
61
+ # @!method primary_county_subdivision
62
+ # @return [USGeo::CountySubdivision] County subdivision that contains most of the ZCTA's land area.
63
+ belongs_to :primary_county_subdivision, foreign_key: :primary_county_subdivision_geoid, class_name: "USGeo::CountySubdivision"
64
+
65
+ # @!method zcta_places
66
+ # @return [ActiveRecord::Relation] ZCTA to place mappings.
67
+ has_many :zcta_places, -> { not_removed }, foreign_key: :zipcode, inverse_of: :zcta, dependent: :destroy
68
+
69
+ # @!method places
70
+ # @return [ActiveRecord::Relation] Places that this ZCTA is a part of.
71
+ has_many :places, -> { not_removed }, through: :zcta_places
72
+
73
+ # @!method primary_place
74
+ # @return [USGeo::Place] Place that contains most of the ZCTA's land area.
75
+ belongs_to :primary_place, foreign_key: :primary_place_geoid, class_name: "USGeo::Place"
76
+
77
+ # @!method zcta_mappings
78
+ # @return [ActiveRecord::Relation] 2010 ZCTA to current ZCTA mappings.
79
+ has_many :zcta_mappings, -> { not_removed }, foreign_key: :zcta_zipcode, inverse_of: :zcta, dependent: :destroy
32
80
 
33
81
  validates :zipcode, length: {is: 5}
34
82
  validates :land_area, numericality: true, presence: true
@@ -36,7 +84,35 @@ module USGeo
36
84
  validates :population, numericality: {only_integer: true}, presence: true
37
85
  validates :housing_units, numericality: {only_integer: true}, presence: true
38
86
 
39
- delegate :core_based_statistical_area, :designated_market_area, :state, :state_code, :time_zone, to: :primary_county, allow_nil: true
87
+ # @!attribute zipcode
88
+ # @return [String] 5-digit ZIP code.
89
+
90
+ # @!method combined_statistical_area
91
+ # @return [USGeo::CombinedStatisticalArea, nil] Combined statistical area that contains the ZCTA.
92
+ delegate :combined_statistical_area, to: :primary_county, allow_nil: true
93
+
94
+ # @!method core_based_statistical_area
95
+ # @return [USGeo::CoreBasedStatisticalArea, nil] Core-based statistical area that contains the ZCTA.
96
+ delegate :core_based_statistical_area, to: :primary_county, allow_nil: true
97
+
98
+ # @!method metropolitan_division
99
+ # @return [USGeo::MetropolitanDivision, nil] Metropolitan division that contains the ZCTA.
100
+ delegate :metropolitan_division, to: :primary_county, allow_nil: true
101
+
102
+ # @!method state
103
+ # @return [USGeo::State] State that contains the ZCTA.
104
+ delegate :state, to: :primary_county, allow_nil: true
105
+
106
+ # @!method state_code
107
+ # @return [String] State code that contains the ZCTA.
108
+ delegate :state_code, to: :primary_county, allow_nil: true
109
+
110
+ # @!method time_zone
111
+ # Get the time zone for the primary county containing the ZCTA. Note that this is not
112
+ # necessarily the time zone for the ZCTA itself since a handful of counties span multiple
113
+ # time zones.
114
+ # @return [ActiveSupport::TimeZone, nil] Time zone for the ZCTA.
115
+ delegate :time_zone, to: :primary_county, allow_nil: true
40
116
 
41
117
  class << self
42
118
  def load!(uri = nil)
@@ -47,10 +123,12 @@ module USGeo
47
123
  load_record!(zipcode: row["ZCTA5"]) do |record|
48
124
  record.primary_county_geoid = row["Primary County"]
49
125
  record.primary_urban_area_geoid = row["Primary Urban Area"]
126
+ record.primary_county_subdivision_geoid = row["Primary County Subdivision"]
127
+ record.primary_place_geoid = row["Primary Place"]
50
128
  record.population = row["Population"]
51
129
  record.housing_units = row["Housing Units"]
52
- record.land_area = area_meters_to_miles(row["Land Area"])
53
- record.water_area = area_meters_to_miles(row["Water Area"])
130
+ record.land_area = row["Land Area"]
131
+ record.water_area = row["Water Area"]
54
132
  record.lat = row["Latitude"]
55
133
  record.lng = row["Longitude"]
56
134
  end
@@ -58,6 +136,5 @@ module USGeo
58
136
  end
59
137
  end
60
138
  end
61
-
62
139
  end
63
140
  end
@@ -1,11 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module USGeo
4
-
5
4
  # Mapping of ZCTA's to counties they overlap with.
6
5
  class ZctaCounty < BaseRecord
7
-
8
- include Demographics
6
+ include Area
9
7
 
10
8
  belongs_to :zcta, foreign_key: :zipcode, inverse_of: :zcta_counties
11
9
  belongs_to :county, foreign_key: :county_geoid, inverse_of: :zcta_counties
@@ -14,31 +12,22 @@ module USGeo
14
12
  validates :county_geoid, length: {is: 5}
15
13
  validates :land_area, numericality: true, presence: true
16
14
  validates :water_area, numericality: true, presence: true
17
- validates :population, numericality: {only_integer: true}, presence: true
18
- validates :housing_units, numericality: {only_integer: true}, presence: true
19
15
 
20
16
  class << self
21
17
  def load!(uri = nil)
22
18
  location = data_uri(uri || "zcta_counties.csv")
23
-
19
+
24
20
  import! do
25
21
  load_data_file(location) do |row|
26
- load_record!(zipcode: row["ZCTA5"], county_geoid: row["GEOID"]) do |record|
27
- record.population = row["Population"]
28
- record.housing_units = row["Housing Units"]
29
- record.land_area = area_meters_to_miles(row["Land Area"])
30
- record.water_area = area_meters_to_miles(row["Water Area"])
22
+ load_record!(zipcode: row["ZCTA5"], county_geoid: row["County GEOID"]) do |record|
23
+ record.land_area = row["Land Area"]
24
+ record.water_area = row["Water Area"]
31
25
  end
32
26
  end
33
27
  end
34
28
  end
35
29
  end
36
30
 
37
- # Percentage of the ZCTA population.
38
- def percent_zcta_population
39
- population.to_f / zcta.population.to_f
40
- end
41
-
42
31
  # Percentage of the ZCTA land area.
43
32
  def percent_zcta_land_area
44
33
  land_area / zcta.land_area
@@ -49,11 +38,6 @@ module USGeo
49
38
  total_area / zcta.total_area
50
39
  end
51
40
 
52
- # Percentage of the county population.
53
- def percent_county_population
54
- population.to_f / county.population.to_f
55
- end
56
-
57
41
  # Percentage of the county land area.
58
42
  def percent_county_land_area
59
43
  land_area / county.land_area
@@ -63,6 +47,5 @@ module USGeo
63
47
  def percent_county_total_area
64
48
  total_area / county.total_area
65
49
  end
66
-
67
50
  end
68
51
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module USGeo
4
+ # Mapping of ZCTA's to counties they overlap with.
5
+ class ZctaCountySubdivision < BaseRecord
6
+ include Area
7
+
8
+ belongs_to :zcta, foreign_key: :zipcode, inverse_of: :zcta_county_subdivisions
9
+ belongs_to :county_subdivision, foreign_key: :county_subdivision_geoid, inverse_of: :zcta_county_subdivisions
10
+
11
+ validates :zipcode, length: {is: 5}
12
+ validates :county_subdivision_geoid, length: {is: 10}
13
+ validates :land_area, numericality: true, presence: true
14
+ validates :water_area, numericality: true, presence: true
15
+
16
+ class << self
17
+ def load!(uri = nil)
18
+ location = data_uri(uri || "zcta_county_subdivisions.csv")
19
+
20
+ import! do
21
+ load_data_file(location) do |row|
22
+ load_record!(zipcode: row["ZCTA5"], county_subdivision_geoid: row["County Subdivision GEOID"]) do |record|
23
+ record.land_area = row["Land Area"]
24
+ record.water_area = row["Water Area"]
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ # Percentage of the ZCTA land area.
32
+ def percent_zcta_land_area
33
+ land_area / zcta.land_area
34
+ end
35
+
36
+ # Percentage of the ZCTA total area.
37
+ def percent_zcta_total_area
38
+ total_area / zcta.total_area
39
+ end
40
+
41
+ # Percentage of the county subdivision land area.
42
+ def percent_county_subdivision_land_area
43
+ land_area / county_subdivision.land_area
44
+ end
45
+
46
+ # Percentage of the county subdivision total area.
47
+ def percent_county_subdivision_total_area
48
+ total_area / county_subdivision.total_area
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module USGeo
4
+ # Mapping of ZIP codes to currently active ZCTA's. The U.S. Postal Service
5
+ # maintains the list of active ZIP codes which can change as population moves
6
+ # around. New ZIP codes are created when a new area is developed and old ZIP
7
+ # are retired when an area is losing population. The Census Bureau updates
8
+ # the list of ZCTA's every 10 years.
9
+ #
10
+ # This mapping table allows looking up the current ZCTA for a ZIP code even
11
+ # if that ZIP code was retired and is no longer in the ZCTA table.
12
+ class ZctaMapping < BaseRecord
13
+ self.table_name = "us_geo_zcta_mappings"
14
+ self.primary_key = "zipcode"
15
+
16
+ belongs_to :zcta, foreign_key: :zcta_zipcode, inverse_of: :zcta_mappings
17
+
18
+ validates :zipcode, length: {is: 5}
19
+ validates :zcta_zipcode, length: {is: 5}
20
+
21
+ class << self
22
+ def load!(uri = nil)
23
+ location = data_uri(uri || "zcta_mappings.csv")
24
+
25
+ import! do
26
+ load_data_file(location) do |row|
27
+ load_record!(zipcode: row["ZIP Code"]) do |record|
28
+ record.zcta_zipcode = row["Active ZCTA5"]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,11 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module USGeo
4
-
5
- # Mapping of ZCTA's to urban areas they overlap with.
4
+ # Mapping of ZCTA's to places they overlap with.
6
5
  class ZctaPlace < BaseRecord
7
-
8
- include Demographics
6
+ include Area
9
7
 
10
8
  belongs_to :zcta, foreign_key: :zipcode, inverse_of: :zcta_places
11
9
  belongs_to :place, foreign_key: :place_geoid, inverse_of: :zcta_places
@@ -14,20 +12,16 @@ module USGeo
14
12
  validates :place_geoid, length: {is: 7}
15
13
  validates :land_area, numericality: true, presence: true
16
14
  validates :water_area, numericality: true, presence: true
17
- validates :population, numericality: {only_integer: true}, presence: true
18
- validates :housing_units, numericality: {only_integer: true}, presence: true
19
15
 
20
16
  class << self
21
17
  def load!(uri = nil)
22
18
  location = data_uri(uri || "zcta_places.csv")
23
-
19
+
24
20
  import! do
25
21
  load_data_file(location) do |row|
26
22
  load_record!(zipcode: row["ZCTA5"], place_geoid: row["Place GEOID"]) do |record|
27
- record.population = row["Population"]
28
- record.housing_units = row["Housing Units"]
29
- record.land_area = area_meters_to_miles(row["Land Area"])
30
- record.water_area = area_meters_to_miles(row["Water Area"])
23
+ record.land_area = row["Land Area"]
24
+ record.water_area = row["Water Area"]
31
25
  end
32
26
  end
33
27
  end
@@ -63,6 +57,5 @@ module USGeo
63
57
  def percent_place_total_area
64
58
  total_area / place.total_area
65
59
  end
66
-
67
60
  end
68
61
  end