dynamodb_geo 0.0.2 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +137 -1
- data/ext/geohash_wrapper/geohash.h +2 -0
- data/ext/geohash_wrapper/geohash_wrapper.c +9 -3
- data/lib/dynamodb_geo.rb +16 -1
- data/lib/dynamodb_geo/version.rb +2 -2
- data/lib/dynamodb_manager.rb +165 -0
- data/lib/geohash.rb +3 -3
- data/lib/geohash/geohash_wrapper.so +0 -0
- data/lib/store.rb +15 -0
- data/spec/dynamodb_geo_spec.rb +18 -0
- data/spec/geohash_spec.rb +8 -0
- data/spec/spec_helper.rb +0 -1
- metadata +6 -4
- data/spec/dynamodb_geo.rb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f54f79a1153702913ca165972a8936865949156e28970e62efc06e23076b0773
|
4
|
+
data.tar.gz: 4171efed028b0cc80b39b35fe951c065da01ac6b7978c11e4264e9da5e0d5be1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04fec0da4cf2f1f62df873fd364dda594028ad566b283bd6ad56573f5d8c156237c5eb691546697001195944a483038931ee4728a8f317d9600b5114bb22af57
|
7
|
+
data.tar.gz: d3a7da451c4e43850c0a3b44db65f967bd28df66ea35848be57d28eb5755a47a1cb1df7a2d87a29bb0af94eec583a889ba0231f35112f4bafa0003a86a539e68
|
data/README.md
CHANGED
@@ -1,7 +1,129 @@
|
|
1
1
|
# DynamoDB_Geo
|
2
|
+
## DynamoDB
|
3
|
+
This is an attempt at storing and querying geohash data in DynamoDB.
|
2
4
|
|
5
|
+
We store objects in DynamoDB, when we query, we look for a customizable number of stored items by zooming out exactly one level.
|
6
|
+
We return the objects in an attempt at the closest items first.
|
3
7
|
|
4
|
-
|
8
|
+
Items are searched as the following.
|
9
|
+
|
10
|
+
Given the lat, long we calculate a hash - assume 9x0qz. We go up one level to 9x0q and calculate all neighbouring hashes.
|
11
|
+
|
12
|
+
9x0p 9x0r 9x0x
|
13
|
+
9x0n 9x0q 9x0w => ["9x0q", "9x0r", "9x0x", "9x0w", "9x0t", "9x0m", "9x0j", "9x0n", "9x0p"]
|
14
|
+
9x0j 9x0m 9x0t
|
15
|
+
|
16
|
+
From this, we ask DynamoDB starting from our own cell, going north, and wrapping clockwise for all objects in these cells up to a configurable number of objects.
|
17
|
+
We then calculate the neighbours of our more local hash 9x0qz, and sort the results of the larger hashes using similar rules.
|
18
|
+
|
19
|
+
9x0rn 9x0rp 9x0x0
|
20
|
+
9x0qy 9x0qz 9x0wb => ["9x0qz", "9x0rp", "9x0x0", "9x0wb", "9x0w8", "9x0qx", "9x0qw", "9x0qy", "9x0rn"]
|
21
|
+
9x0qw 9x0qx 9x0w8
|
22
|
+
|
23
|
+
Using the same pattern as before (Middle -> North -> Clockwise), we sort the returned stores giving priority to the localization.
|
24
|
+
|
25
|
+
### Real talk
|
26
|
+
I know this isn't the most wonderful way to do this, I am still trying to think of something better. Currently it uses up to 8 queries to DynamoDB, I'd like to cut that down to a single query.
|
27
|
+
|
28
|
+
There is a similar library written in Java and JS, but it uses Google S2 for the Geohashing, which has properties that allow them to do the zoom-out technique with a single query, however Google S2 does not exist as a C library (or Ruby library for that matter). The other alternative is Uber H3, however it has the same issues of not being C, or Ruby.
|
29
|
+
|
30
|
+
If we were able to use a unique but deterministic way to calcuate the range key based off of the hash key that would allow us to query every single larger cell in a single batch query. I am currently thinking of more clever ways to do this - obviously I am open to suggestions.
|
31
|
+
|
32
|
+
## Objects
|
33
|
+
### DynamodbManager
|
34
|
+
|
35
|
+
**Attributes**
|
36
|
+
table_name:
|
37
|
+
Sets the DynamoDB Table Name
|
38
|
+
|
39
|
+
hash_key:
|
40
|
+
Sets the name of the primary hash attribute
|
41
|
+
|
42
|
+
range_key:
|
43
|
+
Sets the name of the sort/range attribute
|
44
|
+
|
45
|
+
geohash_key:
|
46
|
+
Sets the name of the localized hash attribute
|
47
|
+
|
48
|
+
geojson_key:
|
49
|
+
Sets the name of the metadata attribute
|
50
|
+
|
51
|
+
hash_key_length:
|
52
|
+
Sets size of the outer hash length
|
53
|
+
|
54
|
+
local_area_size:
|
55
|
+
Sets the size of the inner hash length
|
56
|
+
|
57
|
+
max_item_return:
|
58
|
+
Sets the max number of items to return
|
59
|
+
|
60
|
+
**Methods**
|
61
|
+
Initialization
|
62
|
+
|
63
|
+
Description: Creates a new DynamodbManager object. Inputs are variables to your AWS account.
|
64
|
+
If access_key_id and secret_access_key are provided they are used.
|
65
|
+
If not provided, it falls back to ENV variables, then secret credential storage (profile name).
|
66
|
+
All arguments are keyword arguments
|
67
|
+
Input: region => String
|
68
|
+
table_name => String
|
69
|
+
access_key_id => String
|
70
|
+
secret_access_key => String
|
71
|
+
profile_name => 'default'
|
72
|
+
Output: Aws::DynamoDB::Client
|
73
|
+
|
74
|
+
#new => Object
|
75
|
+
|
76
|
+
Building and describing a DynamoDB Table
|
77
|
+
|
78
|
+
Description: Shows the current configured table, or creates a table to configured as requested
|
79
|
+
Input:
|
80
|
+
Output: Aws::DynamoDB::Types::DescribeTableOutput
|
81
|
+
|
82
|
+
#table => Object
|
83
|
+
|
84
|
+
Creating a new item
|
85
|
+
|
86
|
+
Description: Inserts a new item
|
87
|
+
Input: Store
|
88
|
+
Output: Aws::DynamoDB::Types::PutItemOutput
|
89
|
+
|
90
|
+
#put_store => Object
|
91
|
+
|
92
|
+
Querying stores
|
93
|
+
|
94
|
+
Description: Look for stores dependent on the input Lat, Long (as described above)
|
95
|
+
Input: Store
|
96
|
+
Output: Array[Store]
|
97
|
+
|
98
|
+
#get_stores => Array[Store]
|
99
|
+
|
100
|
+
### Store
|
101
|
+
|
102
|
+
**Methods**
|
103
|
+
Initialization
|
104
|
+
|
105
|
+
Description: Initialization
|
106
|
+
Input: Hash => {
|
107
|
+
latitude # Required
|
108
|
+
longitude # Required
|
109
|
+
address
|
110
|
+
city
|
111
|
+
state
|
112
|
+
zip
|
113
|
+
area_code
|
114
|
+
phone
|
115
|
+
name
|
116
|
+
geohash # Calculated based on lat,long if not provided
|
117
|
+
}
|
118
|
+
Output: Store
|
119
|
+
|
120
|
+
#new => Store
|
121
|
+
|
122
|
+
### DynamodbGeo
|
123
|
+
This only exists as a quick and easy way to create a DynamodbManager. The only method is `.new` and it passes all arguments along to DynamodbManager and returns an instance of DynamodbManager
|
124
|
+
|
125
|
+
|
126
|
+
## Geohashing
|
5
127
|
Includes a Geohash implimentation written in C
|
6
128
|
<https://github.com/simplegeo/libgeohash>
|
7
129
|
|
@@ -43,6 +165,19 @@ Viewing all my neighbours
|
|
43
165
|
|
44
166
|
Geohash.neighbours(hash) => Array[Geohash]
|
45
167
|
|
168
|
+
Viewing one of my neighbours
|
169
|
+
|
170
|
+
Description: Takes in a Geohash and shows the neighbour in the cardinal direction
|
171
|
+
NORTH = 0
|
172
|
+
EAST = 1
|
173
|
+
SOUTH = 2
|
174
|
+
WEST = 3
|
175
|
+
Input: Geohash => String
|
176
|
+
Direction => Integer
|
177
|
+
Output: Geohash
|
178
|
+
|
179
|
+
Geohash.neighbour(hash) => Geohash
|
180
|
+
|
46
181
|
Get width and height about a specific precision
|
47
182
|
|
48
183
|
Description: Takes in a precision value, returns the height and width of the box
|
@@ -51,5 +186,6 @@ Get width and height about a specific precision
|
|
51
186
|
|
52
187
|
Geohash.dimensions(precision) => Dimension
|
53
188
|
|
189
|
+
### Objects
|
54
190
|
#### Geocoord(Object) => attr_accessor: :latitude, :longitude, :north, :south, :east, :west, :dimension
|
55
191
|
#### Dimension(Object) => attr_accessor: :length, :width
|
@@ -71,6 +71,8 @@ extern GeoCoord geohash_decode(char* hash);
|
|
71
71
|
*/
|
72
72
|
extern char** geohash_neighbors(char* hash);
|
73
73
|
|
74
|
+
// sorry I added this, this was not in the original header
|
75
|
+
extern char* get_neighbor(char *hash, int direction);
|
74
76
|
/*
|
75
77
|
* Returns the width and height of a precision value.
|
76
78
|
*/
|
@@ -6,7 +6,8 @@
|
|
6
6
|
void Init_geohash_wrapper();
|
7
7
|
VALUE wrap_geohash_encode(VALUE self, VALUE lat, VALUE lng, VALUE precision);
|
8
8
|
VALUE wrap_geohash_decode(VALUE self, VALUE hash);
|
9
|
-
VALUE
|
9
|
+
VALUE wrap_geohash_neighbours(VALUE self, VALUE hash);
|
10
|
+
VALUE wrap_geohash_neighbour(VALUE self, VALUE hash, VALUE direction);
|
10
11
|
VALUE wrap_geohash_dimensions_for_precision(VALUE self, VALUE precision);
|
11
12
|
|
12
13
|
|
@@ -17,7 +18,8 @@ void Init_geohash_wrapper()
|
|
17
18
|
|
18
19
|
rb_define_singleton_method(Geohash, "encode", wrap_geohash_encode, 3);
|
19
20
|
rb_define_singleton_method(Geohash, "wrap_decode", wrap_geohash_decode, 1);
|
20
|
-
rb_define_singleton_method(Geohash, "neighbours",
|
21
|
+
rb_define_singleton_method(Geohash, "neighbours", wrap_geohash_neighbours, 1);
|
22
|
+
rb_define_singleton_method(Geohash, "neighbour", wrap_geohash_neighbour, 2);
|
21
23
|
rb_define_singleton_method(Geohash, "dimensions_for_precision", wrap_geohash_dimensions_for_precision, 1);
|
22
24
|
}
|
23
25
|
|
@@ -46,7 +48,7 @@ VALUE wrap_geohash_decode(VALUE self, VALUE hash) {
|
|
46
48
|
return r_hash;
|
47
49
|
}
|
48
50
|
|
49
|
-
VALUE
|
51
|
+
VALUE wrap_geohash_neighbours(VALUE self, VALUE hash) {
|
50
52
|
char** hashed_neighbours = geohash_neighbors(StringValueCStr(hash));
|
51
53
|
VALUE neighbours = rb_ary_new2(8);
|
52
54
|
int i;
|
@@ -57,6 +59,10 @@ VALUE wrap_geohash_neighbors(VALUE self, VALUE hash) {
|
|
57
59
|
return neighbours;
|
58
60
|
}
|
59
61
|
|
62
|
+
VALUE wrap_geohash_neighbour(VALUE self, VALUE hash, VALUE direction) {
|
63
|
+
return rb_str_new_cstr(get_neighbor(StringValueCStr(hash), NUM2INT(direction)));
|
64
|
+
}
|
65
|
+
|
60
66
|
VALUE wrap_geohash_dimensions_for_precision(VALUE self, VALUE precision) {
|
61
67
|
GeoBoxDimension dimension;
|
62
68
|
VALUE r_hash = rb_hash_new();
|
data/lib/dynamodb_geo.rb
CHANGED
@@ -1 +1,16 @@
|
|
1
|
-
require '
|
1
|
+
require 'dynamodb_manager'
|
2
|
+
|
3
|
+
module DynamodbGeo
|
4
|
+
class << self
|
5
|
+
def new(region:, table_name:, access_key_id: nil, secret_access_key: nil, profile_name: 'default', endpoint: nil)
|
6
|
+
DynamodbManager.new(
|
7
|
+
region: region,
|
8
|
+
access_key_id: access_key_id,
|
9
|
+
secret_access_key: secret_access_key,
|
10
|
+
profile_name: profile_name,
|
11
|
+
table_name: table_name,
|
12
|
+
endpoint: endpoint
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/dynamodb_geo/version.rb
CHANGED
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'aws-sdk-dynamodb'
|
2
|
+
require 'geohash'
|
3
|
+
require 'store'
|
4
|
+
|
5
|
+
class DynamodbManager
|
6
|
+
attr_accessor :client, :table_name, :hash_key, :range_key, :geohash_key, :geojson, :geohash_index, :hash_key_length, :local_area_size, :max_item_return
|
7
|
+
def initialize(region:, table_name:, access_key_id: nil, secret_access_key: nil, profile_name: 'default', endpoint: nil)
|
8
|
+
if access_key_id.nil? && secret_access_key.nil?
|
9
|
+
access_key_id = ENV['AWS_ACCESS_KEY_ID']
|
10
|
+
secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
|
11
|
+
|
12
|
+
credentials = Aws::SharedCredentials.new(profile_name: profile_name).credentials if access_key_id.nil? && secret_access_key.nil?
|
13
|
+
end
|
14
|
+
credentials = Aws::Credentials.new(access_key_id, secret_access_key)
|
15
|
+
|
16
|
+
@table_name = table_name
|
17
|
+
@hash_key = 'hashkey'
|
18
|
+
@range_key = 'rangekey'
|
19
|
+
@geohash_key = 'geohash'
|
20
|
+
@geojson = 'geoJson'
|
21
|
+
@geohash_index = 'geohash-index'
|
22
|
+
@hash_key_length = 4
|
23
|
+
@local_area_size = 5
|
24
|
+
@max_item_return = 10
|
25
|
+
|
26
|
+
if endpoint
|
27
|
+
@client = Aws::DynamoDB::Client.new(
|
28
|
+
region: region,
|
29
|
+
credentials: credentials,
|
30
|
+
endpoint: endpoint
|
31
|
+
)
|
32
|
+
else
|
33
|
+
@client = Aws::DynamoDB::Client.new(
|
34
|
+
region: region,
|
35
|
+
credentials: credentials,
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def table
|
41
|
+
create_table unless @client.list_tables.table_names.include?(@table_name)
|
42
|
+
|
43
|
+
@client.describe_table(table_name: @table_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
def put_store(store)
|
47
|
+
hash = store.geohash[0..(@local_area_size - 1)]
|
48
|
+
json = {
|
49
|
+
latitude: store.lat,
|
50
|
+
longitude: store.long,
|
51
|
+
address: store.address,
|
52
|
+
city: store.city,
|
53
|
+
state: store.state,
|
54
|
+
zip: store.zip,
|
55
|
+
area_code: store.area_code,
|
56
|
+
phone: store.phone,
|
57
|
+
name: store.name,
|
58
|
+
}
|
59
|
+
put_point(hash, json)
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_stores(lat, long)
|
63
|
+
geohash = Geohash.encode(lat, long, @local_area_size)
|
64
|
+
hash = geohash[0..(@hash_key_length - 1)]
|
65
|
+
all_stores = []
|
66
|
+
neighbours = Geohash.neighbours(hash)
|
67
|
+
neighbours.unshift(hash)
|
68
|
+
|
69
|
+
neighbours.each do |neighbour|
|
70
|
+
resp = query(neighbour)
|
71
|
+
resp.items.each do |item|
|
72
|
+
latitude = item[@geojson]['latitude']
|
73
|
+
longitude = item[@geojson]['longitude']
|
74
|
+
address = item[@geojson]['address']
|
75
|
+
city = item[@geojson]['city']
|
76
|
+
state = item[@geojson]['state']
|
77
|
+
zip = item[@geojson]['zip']
|
78
|
+
area_code = item[@geojson]['area_code']
|
79
|
+
phone = item[@geojson]['phone']
|
80
|
+
name = item[@geojson]['name']
|
81
|
+
geohash = item[@geohash_key]
|
82
|
+
all_stores << Store.new(
|
83
|
+
latitude: latitude,
|
84
|
+
longitude: longitude,
|
85
|
+
address: address,
|
86
|
+
city: city,
|
87
|
+
state: state,
|
88
|
+
zip: zip,
|
89
|
+
area_code: area_code,
|
90
|
+
phone: phone,
|
91
|
+
name: name,
|
92
|
+
geohash: geohash
|
93
|
+
)
|
94
|
+
end
|
95
|
+
break if all_stores.length >= max_item_return
|
96
|
+
end
|
97
|
+
|
98
|
+
# We got all the stores in the biggest possible area, we increase the hash by one and search around now
|
99
|
+
neighbours = Geohash.neighbours(geohash)
|
100
|
+
|
101
|
+
closest_stores = all_stores.select { |store| store.geohash == geohash }
|
102
|
+
surrounding_stores = (all_stores - closest_stores).select { |store| neighbours.include?(store.geohash) }
|
103
|
+
remaining_stores = all_stores - (closest_stores + surrounding_stores)
|
104
|
+
|
105
|
+
return closest_stores + surrounding_stores + remaining_stores
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def query(hash)
|
111
|
+
client.query({
|
112
|
+
table_name: @table_name,
|
113
|
+
index_name: @geohash_index,
|
114
|
+
expression_attribute_values: {
|
115
|
+
':hash' => hash,
|
116
|
+
},
|
117
|
+
key_condition_expression: "#{@hash_key} = :hash",
|
118
|
+
})
|
119
|
+
end
|
120
|
+
|
121
|
+
def put_point(hash, json)
|
122
|
+
uuid = SecureRandom.uuid
|
123
|
+
|
124
|
+
@client.put_item({
|
125
|
+
table_name: @table_name,
|
126
|
+
item: {
|
127
|
+
@hash_key => hash[0..(@hash_key_length - 1)],
|
128
|
+
@range_key => uuid,
|
129
|
+
@geohash_key => hash,
|
130
|
+
@geojson => json
|
131
|
+
}
|
132
|
+
})
|
133
|
+
end
|
134
|
+
|
135
|
+
def create_table
|
136
|
+
@client.create_table({
|
137
|
+
attribute_definitions: [
|
138
|
+
{ attribute_name: @hash_key, attribute_type: 'S' },
|
139
|
+
{ attribute_name: @range_key, attribute_type: 'S' },
|
140
|
+
{ attribute_name: @geohash_key, attribute_type: 'S' }
|
141
|
+
],
|
142
|
+
key_schema: [
|
143
|
+
{ attribute_name: @hash_key, key_type: 'HASH' },
|
144
|
+
{ attribute_name: @range_key, key_type: 'RANGE' }
|
145
|
+
],
|
146
|
+
local_secondary_indexes: [
|
147
|
+
{
|
148
|
+
index_name: @geohash_index,
|
149
|
+
key_schema: [
|
150
|
+
{ attribute_name: @hash_key, key_type: 'HASH' },
|
151
|
+
{ attribute_name: @geohash_key, key_type: 'RANGE' }
|
152
|
+
],
|
153
|
+
projection: {
|
154
|
+
projection_type: "ALL"
|
155
|
+
}
|
156
|
+
}
|
157
|
+
],
|
158
|
+
provisioned_throughput: {
|
159
|
+
read_capacity_units: 10,
|
160
|
+
write_capacity_units: 5,
|
161
|
+
},
|
162
|
+
table_name: @table_name
|
163
|
+
})
|
164
|
+
end
|
165
|
+
end
|
data/lib/geohash.rb
CHANGED
@@ -26,10 +26,10 @@ class Geocoord
|
|
26
26
|
end
|
27
27
|
|
28
28
|
class Dimension
|
29
|
-
attr_accessor :
|
29
|
+
attr_accessor :height, :width
|
30
30
|
|
31
31
|
def initialize(geobox)
|
32
|
-
|
33
|
-
width = geobox['width']
|
32
|
+
@height = geobox['height']
|
33
|
+
@width = geobox['width']
|
34
34
|
end
|
35
35
|
end
|
Binary file
|
data/lib/store.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
class Store
|
2
|
+
attr_accessor :lat, :long, :address, :city, :state, :zip, :area_code, :phone, :name, :geohash
|
3
|
+
def initialize(store_data)
|
4
|
+
@lat = store_data[:latitude]
|
5
|
+
@long = store_data[:longitude]
|
6
|
+
@address = store_data[:address]
|
7
|
+
@city = store_data[:city]
|
8
|
+
@state = store_data[:state]
|
9
|
+
@zip = store_data[:zip]
|
10
|
+
@area_code = store_data[:area_code]
|
11
|
+
@phone = store_data[:phone]
|
12
|
+
@name = store_data[:name]
|
13
|
+
@geohash = store_data[:geohash] || Geohash.encode(lat, long, 10)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dynamodb_geo'
|
3
|
+
|
4
|
+
describe DynamodbGeo do
|
5
|
+
describe '.new' do
|
6
|
+
it 'imported properly' do
|
7
|
+
dynamo = DynamodbGeo.new(
|
8
|
+
region: 'us-east-2',
|
9
|
+
table_name: 'geo-test',
|
10
|
+
profile_name: 'test'
|
11
|
+
)
|
12
|
+
expect(dynamo).to be_a DynamodbManager
|
13
|
+
|
14
|
+
dynamo.get_stores(37.746825, -122.413637)
|
15
|
+
puts 'foo'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/spec/geohash_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'geohash'
|
2
3
|
|
3
4
|
# Quick note, I'm not actually testing if the Geohash is accurate or not.
|
4
5
|
# I'm assuming the C Lib I imported is doing that for me properly.
|
@@ -31,4 +32,11 @@ describe Geohash do
|
|
31
32
|
expect(dimensions).to be_a Dimension
|
32
33
|
end
|
33
34
|
end
|
35
|
+
|
36
|
+
describe '.neighbour' do
|
37
|
+
it 'calculates the neighbour in a direction' do
|
38
|
+
north_neighbour = Geohash.neighbour('s', 0)
|
39
|
+
expect(north_neighbour).to be_a String
|
40
|
+
end
|
41
|
+
end
|
34
42
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamodb_geo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Ahn
|
@@ -97,9 +97,11 @@ files:
|
|
97
97
|
- ext/geohash_wrapper/geohash_wrapper.c
|
98
98
|
- lib/dynamodb_geo.rb
|
99
99
|
- lib/dynamodb_geo/version.rb
|
100
|
+
- lib/dynamodb_manager.rb
|
100
101
|
- lib/geohash.rb
|
101
102
|
- lib/geohash/geohash_wrapper.so
|
102
|
-
-
|
103
|
+
- lib/store.rb
|
104
|
+
- spec/dynamodb_geo_spec.rb
|
103
105
|
- spec/geohash_spec.rb
|
104
106
|
- spec/spec_helper.rb
|
105
107
|
homepage:
|
@@ -125,8 +127,8 @@ requirements: []
|
|
125
127
|
rubygems_version: 3.1.2
|
126
128
|
signing_key:
|
127
129
|
specification_version: 4
|
128
|
-
summary: dynamodb_geo-0.
|
130
|
+
summary: dynamodb_geo-0.1.5
|
129
131
|
test_files:
|
130
|
-
- spec/
|
132
|
+
- spec/dynamodb_geo_spec.rb
|
131
133
|
- spec/geohash_spec.rb
|
132
134
|
- spec/spec_helper.rb
|
data/spec/dynamodb_geo.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|