├── .gitignore ├── .rubocop.yml ├── Gemfile ├── Gemfile.lock ├── LICENSE.txt ├── README.md ├── Rakefile ├── lib ├── data │ └── US.yml └── zip-codes.rb └── zip-codes.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | lib/data/*.txt 19 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | require: 2 | - rubocop-rake 3 | 4 | AllCops: 5 | TargetRubyVersion: 3.0 6 | 7 | Gemspec/DeprecatedAttributeAssignment: # new in 1.30 8 | Enabled: true 9 | Gemspec/RequireMFA: # new in 1.23 10 | Enabled: true 11 | Layout/LineContinuationLeadingSpace: # new in 1.31 12 | Enabled: true 13 | Layout/LineContinuationSpacing: # new in 1.31 14 | Enabled: true 15 | Layout/LineEndStringConcatenationIndentation: # new in 1.18 16 | Enabled: true 17 | Layout/SpaceBeforeBrackets: # new in 1.7 18 | Enabled: true 19 | Lint/AmbiguousAssignment: # new in 1.7 20 | Enabled: true 21 | Lint/AmbiguousOperatorPrecedence: # new in 1.21 22 | Enabled: true 23 | Lint/AmbiguousRange: # new in 1.19 24 | Enabled: true 25 | Lint/ConstantOverwrittenInRescue: # new in 1.31 26 | Enabled: true 27 | Lint/DeprecatedConstants: # new in 1.8 28 | Enabled: true 29 | Lint/DuplicateBranch: # new in 1.3 30 | Enabled: true 31 | Lint/DuplicateMagicComment: # new in 1.37 32 | Enabled: true 33 | Lint/DuplicateRegexpCharacterClassElement: # new in 1.1 34 | Enabled: true 35 | Lint/EmptyBlock: # new in 1.1 36 | Enabled: true 37 | Lint/EmptyClass: # new in 1.3 38 | Enabled: true 39 | Lint/EmptyInPattern: # new in 1.16 40 | Enabled: true 41 | Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21 42 | Enabled: true 43 | Lint/LambdaWithoutLiteralBlock: # new in 1.8 44 | Enabled: true 45 | Lint/NoReturnInBeginEndBlocks: # new in 1.2 46 | Enabled: true 47 | Lint/NonAtomicFileOperation: # new in 1.31 48 | Enabled: true 49 | Lint/NumberedParameterAssignment: # new in 1.9 50 | Enabled: true 51 | Lint/OrAssignmentToConstant: # new in 1.9 52 | Enabled: true 53 | Lint/RedundantDirGlobSort: # new in 1.8 54 | Enabled: true 55 | Lint/RefinementImportMethods: # new in 1.27 56 | Enabled: true 57 | Lint/RequireRangeParentheses: # new in 1.32 58 | Enabled: true 59 | Lint/RequireRelativeSelfPath: # new in 1.22 60 | Enabled: true 61 | Lint/SymbolConversion: # new in 1.9 62 | Enabled: true 63 | Lint/ToEnumArguments: # new in 1.1 64 | Enabled: true 65 | Lint/TripleQuotes: # new in 1.9 66 | Enabled: true 67 | Lint/UnexpectedBlockArity: # new in 1.5 68 | Enabled: true 69 | Lint/UnmodifiedReduceAccumulator: # new in 1.1 70 | Enabled: true 71 | Lint/UselessRuby2Keywords: # new in 1.23 72 | Enabled: true 73 | Naming/BlockForwarding: # new in 1.24 74 | Enabled: true 75 | Security/CompoundHash: # new in 1.28 76 | Enabled: true 77 | Security/IoMethods: # new in 1.22 78 | Enabled: true 79 | Style/ArgumentsForwarding: # new in 1.1 80 | Enabled: true 81 | Style/CollectionCompact: # new in 1.2 82 | Enabled: true 83 | Style/DocumentDynamicEvalDefinition: # new in 1.1 84 | Enabled: true 85 | Style/EmptyHeredoc: # new in 1.32 86 | Enabled: true 87 | Style/EndlessMethod: # new in 1.8 88 | Enabled: true 89 | Style/EnvHome: # new in 1.29 90 | Enabled: true 91 | Style/FetchEnvVar: # new in 1.28 92 | Enabled: true 93 | Style/FileRead: # new in 1.24 94 | Enabled: true 95 | Style/FileWrite: # new in 1.24 96 | Enabled: true 97 | Style/HashConversion: # new in 1.10 98 | Enabled: true 99 | Style/HashExcept: # new in 1.7 100 | Enabled: true 101 | Style/IfWithBooleanLiteralBranches: # new in 1.9 102 | Enabled: true 103 | Style/InPatternThen: # new in 1.16 104 | Enabled: true 105 | Style/MagicCommentFormat: # new in 1.35 106 | Enabled: true 107 | Style/MapCompactWithConditionalBlock: # new in 1.30 108 | Enabled: true 109 | Style/MapToHash: # new in 1.24 110 | Enabled: true 111 | Style/MultilineInPatternThen: # new in 1.16 112 | Enabled: true 113 | Style/NegatedIfElseCondition: # new in 1.2 114 | Enabled: true 115 | Style/NestedFileDirname: # new in 1.26 116 | Enabled: true 117 | Style/NilLambda: # new in 1.3 118 | Enabled: true 119 | Style/NumberedParameters: # new in 1.22 120 | Enabled: true 121 | Style/NumberedParametersLimit: # new in 1.22 122 | Enabled: true 123 | Style/ObjectThen: # new in 1.28 124 | Enabled: true 125 | Style/OpenStructUse: # new in 1.23 126 | Enabled: true 127 | Style/OperatorMethodCall: # new in 1.37 128 | Enabled: true 129 | Style/QuotedSymbols: # new in 1.16 130 | Enabled: true 131 | Style/RedundantArgument: # new in 1.4 132 | Enabled: true 133 | Style/RedundantEach: # new in 1.38 134 | Enabled: true 135 | Style/RedundantInitialize: # new in 1.27 136 | Enabled: true 137 | Style/RedundantSelfAssignmentBranch: # new in 1.19 138 | Enabled: true 139 | Style/RedundantStringEscape: # new in 1.37 140 | Enabled: true 141 | Style/SelectByRegexp: # new in 1.22 142 | Enabled: true 143 | Style/StringChars: # new in 1.12 144 | Enabled: true 145 | Style/SwapValues: # new in 1.1 146 | Enabled: true -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | gemspec 6 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | zip-codes (0.2.1) 5 | 6 | GEM 7 | remote: https://rubygems.org/ 8 | specs: 9 | ast (2.4.2) 10 | json (2.6.2) 11 | parallel (1.22.1) 12 | parser (3.1.3.0) 13 | ast (~> 2.4.1) 14 | rainbow (3.1.1) 15 | rake (13.0.6) 16 | regexp_parser (2.6.1) 17 | rexml (3.2.5) 18 | rubocop (1.39.0) 19 | json (~> 2.3) 20 | parallel (~> 1.10) 21 | parser (>= 3.1.2.1) 22 | rainbow (>= 2.2.2, < 4.0) 23 | regexp_parser (>= 1.8, < 3.0) 24 | rexml (>= 3.2.5, < 4.0) 25 | rubocop-ast (>= 1.23.0, < 2.0) 26 | ruby-progressbar (~> 1.7) 27 | unicode-display_width (>= 1.4.0, < 3.0) 28 | rubocop-ast (1.24.0) 29 | parser (>= 3.1.1.0) 30 | rubocop-rake (0.6.0) 31 | rubocop (~> 1.0) 32 | ruby-progressbar (1.11.0) 33 | unicode-display_width (2.3.0) 34 | 35 | PLATFORMS 36 | ruby 37 | 38 | DEPENDENCIES 39 | rake (~> 13.0.0) 40 | rubocop (~> 1.39.0) 41 | rubocop-rake (~> 0.6.0) 42 | zip-codes! 43 | 44 | BUNDLED WITH 45 | 2.3.26 46 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2014 Monterail.com LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZipCodes [![Gem Version](https://badge.fury.io/rb/zip-codes.png)](http://badge.fury.io/rb/zip-codes) 2 | 3 | Simple gem to get city, state, and time zone for a given zip code. It has a yaml database bundled with it, so you need several mb of memory for the whole hash. 4 | 5 | The gem currently supports only US zip codes. The data origin is https://download.geonames.org/export/zip/ 6 | 7 | The main maintainer is https://github.com/brodyhoskins 8 | 9 | ## Installation 10 | 11 | Add this line to your application's Gemfile: 12 | 13 | gem 'zip-codes' 14 | 15 | And then execute: 16 | 17 | $ bundle 18 | 19 | Or install it yourself as: 20 | 21 | $ gem install zip-codes 22 | 23 | ## Usage 24 | 25 | ```ruby 26 | ZipCodes.identify('30301') 27 | # => {:state_code=>"GA", :state_name=>"Georgia", :city=>"Atlanta", :time_zone=>"America/New_York"} 28 | # First run will take a while, as the yaml has to be loaded 29 | ``` 30 | 31 | If you are using Rails, you can load the hash on app startup for production and staging. 32 | ```ruby 33 | # config/initializers/load_zip_codes.rb 34 | ZipCodes.load unless Rails.env.development? 35 | ``` 36 | 37 | ## Contributing 38 | 39 | 1. Fork it 40 | 2. Create your feature branch (`git checkout -b my-new-feature`) 41 | 3. Commit your changes (`git commit -am 'Add some feature'`) 42 | 4. Push to the branch (`git push origin my-new-feature`) 43 | 5. Create new Pull Request 44 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler/gem_tasks' 4 | require 'yaml' 5 | 6 | task :convert do 7 | codes = {} 8 | File.open('lib/data/US.txt').each_line do |line| 9 | array = line.split('\t') 10 | codes[array[1]] = { 11 | state_code: array[4], 12 | state_name: array[3], 13 | city: array[2] 14 | } 15 | end 16 | 17 | File.write('lib/data/US.yml', codes.to_yaml) 18 | end 19 | -------------------------------------------------------------------------------- /lib/zip-codes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'yaml' 4 | 5 | module ZipCodes 6 | VERSION = '0.3.6' 7 | 8 | class << self 9 | def identify(code) 10 | db[code] 11 | end 12 | 13 | def db 14 | @db ||= begin 15 | path = File.join(__dir__, 'data', 'US.yml') 16 | ::YAML.safe_load_file(path, permitted_classes: [Symbol]) 17 | end 18 | end 19 | 20 | def load 21 | db 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /zip-codes.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path('lib', __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require 'zip-codes' 6 | 7 | Gem::Specification.new do |spec| 8 | spec.name = 'zip-codes' 9 | spec.version = ZipCodes::VERSION 10 | spec.authors = ['Michał Duda'] 11 | spec.email = ['michal.duda@monterail.com'] 12 | spec.description = %s(Simple gem to get city, state, and time zone for a given zip code) 13 | spec.summary = %s(Gem to identify zip codes inside US) 14 | spec.homepage = 'https://github.com/monterail/zip-codes' 15 | spec.license = 'MIT' 16 | 17 | spec.files = `git ls-files`.split($RS) 18 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 19 | spec.require_paths = ['lib'] 20 | 21 | spec.required_ruby_version = '>= 3.0.0' 22 | 23 | spec.add_development_dependency 'rake', '~> 13.0.0' 24 | spec.add_development_dependency 'rubocop', '~> 1.39.0' 25 | spec.add_development_dependency 'rubocop-rake', '~> 0.6.0' 26 | end 27 | --------------------------------------------------------------------------------