geo_states 0.1.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.
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module GeoStates
6
+ # Loads country/state data from bundled JSON (no external API at runtime).
7
+ module DataLoader
8
+ DATA_DIR = File.expand_path("data", __dir__)
9
+ COUNTRIES_FILE = File.join(DATA_DIR, "countries.json")
10
+
11
+ class << self
12
+ def load_countries
13
+ @countries = nil
14
+ raw = File.read(COUNTRIES_FILE)
15
+ list = JSON.parse(raw)
16
+ list.map { |c| normalize_country(c) }
17
+ end
18
+
19
+ def countries
20
+ @countries ||= load_countries
21
+ end
22
+
23
+ def find_by_iso2(iso2)
24
+ countries.find { |c| c[:iso2].to_s.casecmp(iso2.to_s) == 0 }
25
+ end
26
+
27
+ def find_by_iso3(iso3)
28
+ countries.find { |c| c[:iso3].to_s.casecmp(iso3.to_s) == 0 }
29
+ end
30
+
31
+ def find_by_name(name)
32
+ countries.find { |c| c[:country].to_s.casecmp(name.to_s) == 0 }
33
+ end
34
+
35
+ def find_by_m49(m49)
36
+ code = m49.to_s.strip
37
+ return nil if code.empty?
38
+ code = code.rjust(3, "0") if code.length < 3
39
+ countries.find { |c| c[:m49].to_s == code }
40
+ end
41
+
42
+ private
43
+
44
+ def normalize_country(raw)
45
+ states = (raw["states"] || []).map { |s| normalize_state(s) }
46
+ {
47
+ country: raw["name"],
48
+ m49: raw["m49"],
49
+ iso3: raw["iso3"],
50
+ iso2: raw["iso2"],
51
+ currency: raw["currency"],
52
+ currency_symbol: raw["currency_symbol"],
53
+ phone_code: raw["phone_code"],
54
+ flag: raw["flag"],
55
+ states: states
56
+ }
57
+ end
58
+
59
+ def normalize_state(raw)
60
+ code = raw["state_code"].to_s
61
+ iso2 = code.length >= 2 ? code[0, 2].upcase : code.upcase
62
+ {
63
+ name: raw["name"],
64
+ state_code: code,
65
+ iso3: raw["iso3"] || code,
66
+ iso2: raw["iso2"] || iso2
67
+ }
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GeoStates
4
+ VERSION = "0.1.0"
5
+ end
data/lib/geo_states.rb ADDED
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "geo_states/version"
4
+
5
+ module GeoStates
6
+ class Error < StandardError; end
7
+
8
+ # All countries with states (from bundled data, no network).
9
+ # @return [Array<Hash>]
10
+ def self.all_countries
11
+ DataLoader.countries
12
+ end
13
+
14
+ # Find country by ISO 3166-1 alpha-2 (e.g. "MX", "US").
15
+ # @param iso2 [String]
16
+ # @return [Hash, nil]
17
+ def self.find_country(iso2)
18
+ DataLoader.find_by_iso2(iso2)
19
+ end
20
+
21
+ # Find country by ISO 3166-1 alpha-3 (e.g. "MEX", "USA").
22
+ # @param iso3 [String]
23
+ # @return [Hash, nil]
24
+ def self.find_country_by_iso3(iso3)
25
+ DataLoader.find_by_iso3(iso3)
26
+ end
27
+
28
+ # Find country by name (case-insensitive).
29
+ # @param name [String]
30
+ # @return [Hash, nil]
31
+ def self.find_country_by_name(name)
32
+ DataLoader.find_by_name(name)
33
+ end
34
+
35
+ # States for a country (by iso2, iso3, or country name).
36
+ # @param identifier [String] ISO2, ISO3, or country name
37
+ # @return [Array<Hash>]
38
+ def self.states_for(identifier)
39
+ country = find_country(identifier) ||
40
+ find_country_by_iso3(identifier) ||
41
+ find_country_by_name(identifier)
42
+ country&.dig(:states) || []
43
+ end
44
+ end
@@ -0,0 +1,9 @@
1
+ module GeoStates
2
+ VERSION: String
3
+
4
+ def self.all_countries: () -> Array[Hash[Symbol, untyped]]
5
+ def self.find_country: (String iso2) -> Hash[Symbol, untyped]?
6
+ def self.find_country_by_iso3: (String iso3) -> Hash[Symbol, untyped]?
7
+ def self.find_country_by_name: (String name) -> Hash[Symbol, untyped]?
8
+ def self.states_for: (String identifier) -> Array[Hash[Symbol, untyped]]
9
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geo_states
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alberto Osnaya (@elosnaya)
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2026-02-17 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Lists countries and their states (or provinces, regions) in a consistent
14
+ format. Data is bundled with the gem.
15
+ email:
16
+ - luisosnet@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - LICENSE.txt
22
+ - README.md
23
+ - Rakefile
24
+ - geo_states/data/countries.json
25
+ - lib/geo_states.rb
26
+ - lib/geo_states/data/countries.json
27
+ - lib/geo_states/data_loader.rb
28
+ - lib/geo_states/version.rb
29
+ - sig/geo_states.rbs
30
+ homepage: https://github.com/trasmisora/GeoStates
31
+ licenses:
32
+ - MIT
33
+ metadata:
34
+ homepage_uri: https://github.com/trasmisora/GeoStates
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 3.2.0
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubygems_version: 3.5.3
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: Countries and states/subdivisions from bundled data (no external API at runtime).
54
+ test_files: []