zipcoder 0.4.2 → 0.5.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/README.md +29 -0
- data/lib/zipcoder/cacher/base.rb +144 -145
- data/lib/zipcoder/cacher/memory.rb +35 -0
- data/lib/zipcoder/cacher/redis.rb +46 -0
- data/lib/zipcoder/version.rb +1 -1
- data/lib/zipcoder.rb +2 -2
- data/spec/cacher_redis_spec.rb +48 -0
- data/spec/spec_helper.rb +56 -0
- data/spec/zipcoder_spec.rb +4 -1
- data/zipcoder.gemspec +1 -0
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6acfa10df7bcb97c1d077f57b44eb8f07db3ff49
|
4
|
+
data.tar.gz: 466550b2bbf85a28a1b67381fb6408c71d3b8fcd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 268af7c1b49cd0528cc2caae8d040ee64127063d5cb292f4a26ed62b76e3f910785f74c77425b05466fd0c0ee9e591d7e66d7e26293288d43ac15e4ce2fd4ca7
|
7
|
+
data.tar.gz: f2ba366f03a0ec93c31d62b17fb8ab09ddd274c0e53be3bf1ee3deba1ceecfbf581818faea8f6bba17c608a11baa8e13211a67efdbfbfc5eba399e8d0da284d8
|
data/README.md
CHANGED
@@ -7,6 +7,8 @@ Gem for performing zip code lookup operations
|
|
7
7
|
|
8
8
|
## Revision History
|
9
9
|
|
10
|
+
- v0.5.0:
|
11
|
+
- added Redis backend support
|
10
12
|
- v0.4.2:
|
11
13
|
- updated paths to fix RAILS require issue
|
12
14
|
- v0.4.1:
|
@@ -64,6 +66,33 @@ This will immediately load the data structures. Currently it takes roughly 3s
|
|
64
66
|
to create and import all of the data structures. I will look at ways to
|
65
67
|
reduce this later.
|
66
68
|
|
69
|
+
#### Redis Support
|
70
|
+
|
71
|
+
To use Redis as the cache for zipcoder rather than memory, you must do the
|
72
|
+
following
|
73
|
+
|
74
|
+
**install the 'redis' Gem (or add to your Gemfile if using Rails):**
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
gme 'redis'
|
78
|
+
```
|
79
|
+
|
80
|
+
*Note that this Gem supports Ruby >= 2.0 so I could NOT use the latest Redis
|
81
|
+
version. I had to use v3.3.5 to test.*
|
82
|
+
|
83
|
+
**create a redis cacher and pass it to the "load_cache" method:**
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
require 'zipcoder'
|
87
|
+
require 'zipcoder/cacher/redis'
|
88
|
+
|
89
|
+
cacher = Zipcoder::Cacher::Redis.new(**args)
|
90
|
+
Zipcoder.load_cache(cacher)
|
91
|
+
```
|
92
|
+
|
93
|
+
Please check the [here](https://github.com/redis/redis-rb) for the different
|
94
|
+
options to use when instantiating the "Redis" client.
|
95
|
+
|
67
96
|
### Methods
|
68
97
|
|
69
98
|
The library overrides the String (and in some instances Integer) class to
|
data/lib/zipcoder/cacher/base.rb
CHANGED
@@ -1,111 +1,109 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
module Zipcoder
|
2
|
+
module Cacher
|
3
|
+
# The cacher base class places all of the objects in memory. The
|
4
|
+
# abstraction will later allow us to override for MemCacher and
|
5
|
+
# Redis implementations
|
6
|
+
class Base
|
7
|
+
KEY_BASE = "zipcoder"
|
8
|
+
KEY_ZIP = "#{KEY_BASE}:zip"
|
9
|
+
KEY_CITY = "#{KEY_BASE}:city"
|
10
|
+
KEY_STATE = "#{KEY_BASE}:state"
|
11
|
+
KEY_STATES = "#{KEY_BASE}:states"
|
12
|
+
|
13
|
+
#region Override These
|
14
|
+
def _init_cache(**kwargs)
|
15
|
+
# Override ME
|
16
|
+
end
|
11
17
|
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
def _empty_cache
|
19
|
+
# Override ME
|
20
|
+
end
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
|
22
|
+
def _write_cache(key, value)
|
23
|
+
# Override ME
|
24
|
+
end
|
19
25
|
|
20
|
-
|
21
|
-
|
22
|
-
|
26
|
+
def _read_cache(key)
|
27
|
+
# Override ME
|
28
|
+
end
|
23
29
|
|
24
|
-
|
25
|
-
|
30
|
+
def _iterate_keys(**kwargs, &block)
|
31
|
+
# Override ME
|
32
|
+
end
|
26
33
|
|
27
|
-
|
34
|
+
#endregion
|
28
35
|
|
29
|
-
|
30
|
-
|
31
|
-
block.call(key)
|
32
|
-
end
|
36
|
+
def initialize(**kwargs)
|
37
|
+
self._init_cache **kwargs
|
33
38
|
end
|
34
|
-
end
|
35
39
|
|
36
|
-
|
40
|
+
def load
|
41
|
+
this_dir = File.expand_path(File.dirname(__FILE__))
|
37
42
|
|
38
|
-
|
39
|
-
|
40
|
-
|
43
|
+
# Load zip cache from file
|
44
|
+
zip_data = File.join(this_dir, '..', '..', 'data', 'zip_data.yml')
|
45
|
+
zip_codes = YAML.load(File.open(zip_data))
|
41
46
|
|
42
|
-
|
43
|
-
|
47
|
+
# Initialize
|
48
|
+
_empty_cache
|
49
|
+
city_states = {}
|
50
|
+
state_lookup = {}
|
44
51
|
|
45
|
-
|
46
|
-
|
47
|
-
|
52
|
+
# Add the zip codes to the cache
|
53
|
+
zip_codes.each do |zip, info|
|
54
|
+
city = _capitalize_all(info[:city])
|
55
|
+
info[:city] = city
|
56
|
+
state = info[:state]
|
48
57
|
|
49
|
-
|
50
|
-
|
51
|
-
city_states = {}
|
52
|
-
state_lookup = {}
|
58
|
+
# Iterate through the zip codes and add them to the zip cache
|
59
|
+
_write_cache _zip_cache(zip), info
|
53
60
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
61
|
+
# Create the city lookups
|
62
|
+
city_state = "#{city.upcase},#{state.upcase}"
|
63
|
+
infos = city_states[city_state] || []
|
64
|
+
infos << info
|
65
|
+
city_states[city_state] = infos
|
66
|
+
end
|
59
67
|
|
60
|
-
#
|
61
|
-
|
68
|
+
# Normalize each city and populate the state cache
|
69
|
+
city_states.each do |city_state, infos|
|
70
|
+
city = infos[0][:city]
|
71
|
+
state = infos[0][:state]
|
62
72
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
infos << info
|
67
|
-
city_states[city_state] = infos
|
68
|
-
end
|
73
|
+
# Populate the City Cache
|
74
|
+
normalized = _normalize_city(infos)
|
75
|
+
_write_cache _city_cache(city_state), normalized
|
69
76
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
77
|
+
# Populate the State Cache
|
78
|
+
cities = state_lookup[state] || []
|
79
|
+
cities << city
|
80
|
+
state_lookup[state] = cities
|
81
|
+
end
|
74
82
|
|
75
|
-
#
|
76
|
-
|
77
|
-
|
83
|
+
# Set the cities cache
|
84
|
+
state_lookup.each do |state, cities|
|
85
|
+
_write_cache _state_cache(state), cities.sort
|
86
|
+
end
|
78
87
|
|
79
|
-
#
|
80
|
-
|
81
|
-
cities << city
|
82
|
-
state_lookup[state] = cities
|
88
|
+
# Set the states cache
|
89
|
+
self._write_cache _states, state_lookup.keys.sort
|
83
90
|
end
|
84
91
|
|
85
|
-
|
86
|
-
|
87
|
-
_write_cache _state_cache(state), cities.sort
|
92
|
+
def read_zip_cache(zip)
|
93
|
+
_read_cache _zip_cache(zip)
|
88
94
|
end
|
89
95
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
def read_zip_cache(zip)
|
95
|
-
_read_cache _zip_cache(zip)
|
96
|
-
end
|
97
|
-
|
98
|
-
def read_city_cache(city_state)
|
99
|
-
_read_cache _city_cache(city_state)
|
100
|
-
end
|
96
|
+
def read_city_cache(city_state)
|
97
|
+
_read_cache _city_cache(city_state)
|
98
|
+
end
|
101
99
|
|
102
|
-
|
103
|
-
|
104
|
-
|
100
|
+
def read_state_cache(state)
|
101
|
+
_read_cache _state_cache(state)
|
102
|
+
end
|
105
103
|
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
def read_states
|
105
|
+
_read_cache _states
|
106
|
+
end
|
109
107
|
|
110
108
|
def iterate_zips(&block)
|
111
109
|
return if block == nil
|
@@ -123,72 +121,73 @@ module Cacher
|
|
123
121
|
end
|
124
122
|
end
|
125
123
|
|
126
|
-
|
124
|
+
private
|
127
125
|
|
128
|
-
|
129
|
-
|
130
|
-
|
126
|
+
def _zip_cache(zip)
|
127
|
+
"#{KEY_ZIP}:#{zip}"
|
128
|
+
end
|
131
129
|
|
132
|
-
|
133
|
-
|
134
|
-
|
130
|
+
def _city_cache(city_state)
|
131
|
+
"#{KEY_CITY}:#{city_state}"
|
132
|
+
end
|
135
133
|
|
136
|
-
|
137
|
-
|
138
|
-
|
134
|
+
def _state_cache(state)
|
135
|
+
"#{KEY_STATE}:#{state}"
|
136
|
+
end
|
139
137
|
|
140
|
-
|
141
|
-
|
142
|
-
|
138
|
+
def _states
|
139
|
+
KEY_STATES
|
140
|
+
end
|
143
141
|
|
144
|
-
|
145
|
-
|
146
|
-
|
142
|
+
def _capitalize_all(string)
|
143
|
+
string.split(' ').map {|w| w.capitalize }.join(' ')
|
144
|
+
end
|
147
145
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
# Create the normalized value
|
170
|
-
if infos.count == 0
|
171
|
-
normalized = nil
|
172
|
-
elsif infos.count == 1
|
173
|
-
normalized = {
|
174
|
-
city: infos[0][:city],
|
175
|
-
state: infos[0][:state],
|
176
|
-
zip: infos[0][:zip],
|
177
|
-
lat: infos[0][:lat],
|
178
|
-
long: infos[0][:long],
|
179
|
-
}
|
180
|
-
else
|
181
|
-
normalized = {
|
182
|
-
city: infos[0][:city],
|
183
|
-
state: infos[0][:state],
|
184
|
-
zip: "#{zip_min.to_zip}-#{zip_max.to_zip}",
|
185
|
-
lat: ((lat_min+lat_max)/2).round(4),
|
186
|
-
long: ((long_min+long_max)/2).round(4)
|
187
|
-
}
|
188
|
-
end
|
189
|
-
|
190
|
-
normalized
|
191
|
-
end
|
146
|
+
# Normalizes the values
|
147
|
+
def _normalize_city(infos)
|
148
|
+
# Values
|
149
|
+
zip_min = 100000
|
150
|
+
zip_max = 0
|
151
|
+
lat_min = 200
|
152
|
+
lat_max = -200
|
153
|
+
long_min = 200
|
154
|
+
long_max = -200
|
155
|
+
|
156
|
+
# Iterate through the info and get min/max of zip/lat/long
|
157
|
+
infos.each do |info|
|
158
|
+
zip = info[:zip].to_i
|
159
|
+
zip_min = zip if zip < zip_min
|
160
|
+
zip_max = zip if zip > zip_max
|
161
|
+
lat_min = info[:lat] if info[:lat] < lat_min
|
162
|
+
lat_max = info[:lat] if info[:lat] > lat_max
|
163
|
+
long_min = info[:long] if info[:long] < long_min
|
164
|
+
long_max = info[:long] if info[:long] > long_max
|
165
|
+
end
|
192
166
|
|
167
|
+
# Create the normalized value
|
168
|
+
if infos.count == 0
|
169
|
+
normalized = nil
|
170
|
+
elsif infos.count == 1
|
171
|
+
normalized = {
|
172
|
+
city: infos[0][:city],
|
173
|
+
state: infos[0][:state],
|
174
|
+
zip: infos[0][:zip],
|
175
|
+
lat: infos[0][:lat],
|
176
|
+
long: infos[0][:long],
|
177
|
+
}
|
178
|
+
else
|
179
|
+
normalized = {
|
180
|
+
city: infos[0][:city],
|
181
|
+
state: infos[0][:state],
|
182
|
+
zip: "#{zip_min.to_zip}-#{zip_max.to_zip}",
|
183
|
+
lat: ((lat_min+lat_max)/2).round(4),
|
184
|
+
long: ((long_min+long_max)/2).round(4)
|
185
|
+
}
|
186
|
+
end
|
187
|
+
|
188
|
+
normalized
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
193
192
|
end
|
194
|
-
end
|
193
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
module Zipcoder
|
4
|
+
module Cacher
|
5
|
+
class Memory < Base
|
6
|
+
def _init_cache(**kwargs)
|
7
|
+
@cache = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def _empty_cache
|
11
|
+
@cache.clear
|
12
|
+
end
|
13
|
+
|
14
|
+
def _write_cache(key, value)
|
15
|
+
@cache[key] = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def _read_cache(key)
|
19
|
+
@cache[key]
|
20
|
+
end
|
21
|
+
|
22
|
+
def _iterate_keys(**kwargs, &block)
|
23
|
+
return if block == nil
|
24
|
+
|
25
|
+
start_with = kwargs[:start_with]
|
26
|
+
|
27
|
+
@cache.keys.each do |key|
|
28
|
+
if start_with == nil or key.start_with?(start_with)
|
29
|
+
block.call(key)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
require 'redis'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Zipcoder
|
6
|
+
module Cacher
|
7
|
+
class Redis < Base
|
8
|
+
|
9
|
+
# This is here for stubbing
|
10
|
+
def self._create_redis_client(**kwargs)
|
11
|
+
::Redis.new(**kwargs)
|
12
|
+
end
|
13
|
+
|
14
|
+
def _init_cache(**kwargs)
|
15
|
+
@redis = self.class._create_redis_client(**kwargs)
|
16
|
+
end
|
17
|
+
|
18
|
+
def _empty_cache
|
19
|
+
keys = @redis.keys("#{KEY_BASE}*")
|
20
|
+
@redis.del(*keys) unless keys.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
def _write_cache(key, value)
|
24
|
+
return if value == nil
|
25
|
+
@redis.set(key, value.to_json)
|
26
|
+
end
|
27
|
+
|
28
|
+
def _read_cache(key)
|
29
|
+
data = @redis.get(key)
|
30
|
+
data == nil ? nil : JSON.parse(data, :symbolize_names => true)
|
31
|
+
end
|
32
|
+
|
33
|
+
def _iterate_keys(**kwargs, &block)
|
34
|
+
return if block == nil
|
35
|
+
|
36
|
+
start_with = kwargs[:start_with] || KEY_BASE
|
37
|
+
|
38
|
+
# Redis "keys" command will pre-filter the keys for us so no
|
39
|
+
# need for "if" statement
|
40
|
+
@redis.keys("#{start_with}*").each do |key|
|
41
|
+
block.call(key)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/zipcoder/version.rb
CHANGED
data/lib/zipcoder.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require "zipcoder/version"
|
2
|
-
require "zipcoder/cacher/
|
2
|
+
require "zipcoder/cacher/memory"
|
3
3
|
require "zipcoder/ext/string"
|
4
4
|
require "zipcoder/ext/integer"
|
5
5
|
require "yaml"
|
@@ -19,7 +19,7 @@ module Zipcoder
|
|
19
19
|
|
20
20
|
# Loads the data into memory
|
21
21
|
def self.load_cache(cacher=nil)
|
22
|
-
@@cacher = cacher || Cacher::
|
22
|
+
@@cacher = cacher || Cacher::Memory.new
|
23
23
|
self.cacher.load
|
24
24
|
end
|
25
25
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "zipcoder/cacher/redis"
|
3
|
+
|
4
|
+
|
5
|
+
describe Zipcoder::Cacher::Redis do
|
6
|
+
stub_redis_once = false
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
unless stub_redis_once
|
10
|
+
allow(Zipcoder::Cacher::Redis).to receive(:_create_redis_client) do
|
11
|
+
RedisStub.new
|
12
|
+
end
|
13
|
+
Zipcoder.load_cache Zipcoder::Cacher::Redis.new
|
14
|
+
end
|
15
|
+
|
16
|
+
stub_redis_once = true
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#zip_info" do
|
20
|
+
it "match" do
|
21
|
+
info = "78748".zip_info
|
22
|
+
expect(info[:city]).to eq("Austin")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "matches city" do
|
26
|
+
zips = Zipcoder.zip_info city: "Austin", state: "TX"
|
27
|
+
expect(zips.count).to eq(47)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "no match" do
|
31
|
+
info = "78706".zip_info
|
32
|
+
expect(info).to be_nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#zip_cities" do
|
37
|
+
it "match" do
|
38
|
+
cities = "78748".zip_cities
|
39
|
+
expect(cities.count).to eq(1)
|
40
|
+
expect(cities[0][:city]).to eq("Austin")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "no match" do
|
44
|
+
cities = "78706".zip_cities
|
45
|
+
expect(cities.count).to eq(0)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -9,3 +9,59 @@ end
|
|
9
9
|
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
10
10
|
require "zipcoder"
|
11
11
|
|
12
|
+
class RedisStub
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@cache = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def set(key, value)
|
19
|
+
@cache[key] = value
|
20
|
+
end
|
21
|
+
|
22
|
+
def get(key)
|
23
|
+
@cache[key]
|
24
|
+
end
|
25
|
+
|
26
|
+
def keys(filter=nil)
|
27
|
+
if filter == nil
|
28
|
+
@cache.keys
|
29
|
+
else
|
30
|
+
wildcard_start = false
|
31
|
+
wildcard_end = false
|
32
|
+
|
33
|
+
if filter.start_with? '*'
|
34
|
+
wildcard_start = true
|
35
|
+
filter = filter[1..-1]
|
36
|
+
end
|
37
|
+
|
38
|
+
if filter.end_with? '*'
|
39
|
+
wildcard_end = true
|
40
|
+
filter = filter[0..-2]
|
41
|
+
end
|
42
|
+
|
43
|
+
keys = []
|
44
|
+
@cache.keys.each do |key|
|
45
|
+
if wildcard_start and wildcard_end
|
46
|
+
keys << key if key.include? filter
|
47
|
+
elsif wildcard_start
|
48
|
+
keys << key if key.end_with? filter
|
49
|
+
elsif wildcard_end
|
50
|
+
keys << key if key.start_with? filter
|
51
|
+
elsif filter == key
|
52
|
+
keys << key
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
keys
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def del(*keys)
|
61
|
+
keys.each do |key|
|
62
|
+
@cache.delete(key)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
data/spec/zipcoder_spec.rb
CHANGED
data/zipcoder.gemspec
CHANGED
@@ -24,5 +24,6 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency 'rspec', '>= 3.5.0'
|
25
25
|
spec.add_development_dependency 'simplecov'
|
26
26
|
spec.add_development_dependency 'codecov'
|
27
|
+
spec.add_development_dependency 'redis', "~> 3.3.5"
|
27
28
|
spec.required_ruby_version = '>= 2.0'
|
28
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zipcoder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Chapman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03-
|
11
|
+
date: 2018-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: redis
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 3.3.5
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 3.3.5
|
83
97
|
description:
|
84
98
|
email:
|
85
99
|
- eric.chappy@gmail.com
|
@@ -103,9 +117,12 @@ files:
|
|
103
117
|
- lib/data/zipcode.csv
|
104
118
|
- lib/zipcoder.rb
|
105
119
|
- lib/zipcoder/cacher/base.rb
|
120
|
+
- lib/zipcoder/cacher/memory.rb
|
121
|
+
- lib/zipcoder/cacher/redis.rb
|
106
122
|
- lib/zipcoder/ext/integer.rb
|
107
123
|
- lib/zipcoder/ext/string.rb
|
108
124
|
- lib/zipcoder/version.rb
|
125
|
+
- spec/cacher_redis_spec.rb
|
109
126
|
- spec/spec_helper.rb
|
110
127
|
- spec/zipcoder_spec.rb
|
111
128
|
- zipcoder.gemspec
|
@@ -134,5 +151,6 @@ signing_key:
|
|
134
151
|
specification_version: 4
|
135
152
|
summary: Converts zip codes to cities, lat/long, and vice-versa
|
136
153
|
test_files:
|
154
|
+
- spec/cacher_redis_spec.rb
|
137
155
|
- spec/spec_helper.rb
|
138
156
|
- spec/zipcoder_spec.rb
|