dynamodb_geo 0.0.2 → 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.
- checksums.yaml +4 -4
- data/README.md +135 -1
- data/ext/geohash_wrapper/geohash.h +2 -0
- data/ext/geohash_wrapper/geohash_wrapper.c +9 -3
- data/lib/dynamodb_geo.rb +15 -1
- data/lib/dynamodb_geo/version.rb +2 -2
- data/lib/dynamodb_manager.rb +136 -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: 2462d22ee572cb65c0af6c6c924bb32f7cbc29fabbf60b15f63be209da271a8a
|
|
4
|
+
data.tar.gz: 2c611dfab3f4caa02c25911e4fcb16f6b4a47006a467b37a8df1cbb8b646a182
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e7f45d33d1b1ff2ed85dfcaf06c2336ad9ecae230483ff9da9039ce38b69b37f632dfa896bb3ce91611eff32a98249f52ed2a257483cdbbda9a0f478e6d92787
|
|
7
|
+
data.tar.gz: d60bdecd1555c1dfae86bbb034d8c38ede68f55c44d824ad6e7e1c3a1c5f71bd364192d5d8ae4a51affaeede24d23bd1194a1b722a9e21eb10cbbbe2b59782a4
|
data/README.md
CHANGED
|
@@ -1,7 +1,127 @@
|
|
|
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. Returned in an attempt at the closest items first.
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
Items are searched as the following.
|
|
8
|
+
Given the lat, long we calculate a hash 9x0qz. We go up one level to 9x0q and calculate all neighbouring hashes.
|
|
9
|
+
|
|
10
|
+
9x0p 9x0r 9x0x
|
|
11
|
+
9x0n 9x0q 9x0w => ["9x0q", "9x0r", "9x0x", "9x0w", "9x0t", "9x0m", "9x0j", "9x0n", "9x0p"]
|
|
12
|
+
9x0j 9x0m 9x0t
|
|
13
|
+
|
|
14
|
+
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.
|
|
15
|
+
We then calculate the neighbours of our more local hash 9x0qz, and sort the results of the larger hashes using similar rules.
|
|
16
|
+
|
|
17
|
+
9x0rn 9x0rp 9x0x0
|
|
18
|
+
9x0qy 9x0qz 9x0wb => ["9x0qz", "9x0rp", "9x0x0", "9x0wb", "9x0w8", "9x0qx", "9x0qw", "9x0qy", "9x0rn"]
|
|
19
|
+
9x0qw 9x0qx 9x0w8
|
|
20
|
+
|
|
21
|
+
Using the same pattern as before (Middle -> North -> Clockwise), we sort the returned stores giving priority to the localization.
|
|
22
|
+
|
|
23
|
+
### Real talk
|
|
24
|
+
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.
|
|
25
|
+
|
|
26
|
+
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.
|
|
27
|
+
|
|
28
|
+
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.
|
|
29
|
+
|
|
30
|
+
## Objects
|
|
31
|
+
### DynamodbManager
|
|
32
|
+
|
|
33
|
+
**Attributes**
|
|
34
|
+
table_name:
|
|
35
|
+
Sets the DynamoDB Table Name
|
|
36
|
+
|
|
37
|
+
hash_key:
|
|
38
|
+
Sets the name of the primary hash attribute
|
|
39
|
+
|
|
40
|
+
range_key:
|
|
41
|
+
Sets the name of the sort/range attribute
|
|
42
|
+
|
|
43
|
+
geohash_key:
|
|
44
|
+
Sets the name of the localized hash attribute
|
|
45
|
+
|
|
46
|
+
geojson_key:
|
|
47
|
+
Sets the name of the metadata attribute
|
|
48
|
+
|
|
49
|
+
hash_key_length:
|
|
50
|
+
Sets size of the outer hash length
|
|
51
|
+
|
|
52
|
+
local_area_size:
|
|
53
|
+
Sets the size of the inner hash length
|
|
54
|
+
|
|
55
|
+
max_item_return:
|
|
56
|
+
Sets the max number of items to return
|
|
57
|
+
|
|
58
|
+
**Methods**
|
|
59
|
+
Initialization
|
|
60
|
+
|
|
61
|
+
Description: Creates a new DynamodbManager object. Inputs are variables to your AWS account.
|
|
62
|
+
If access_key_id and secret_access_key are provided they are used.
|
|
63
|
+
If not provided, it falls back to ENV variables, then secret credential storage (profile name).
|
|
64
|
+
All arguments are keyword arguments
|
|
65
|
+
Input: region => String
|
|
66
|
+
table_name => String
|
|
67
|
+
access_key_id => String
|
|
68
|
+
secret_access_key => String
|
|
69
|
+
profile_name => 'default'
|
|
70
|
+
Output: Aws::DynamoDB::Client
|
|
71
|
+
|
|
72
|
+
#new => Object
|
|
73
|
+
|
|
74
|
+
Building and describing a DynamoDB Table
|
|
75
|
+
|
|
76
|
+
Description: Shows the current configured table, or creates a table to configured as requested
|
|
77
|
+
Input:
|
|
78
|
+
Output: Aws::DynamoDB::Types::DescribeTableOutput
|
|
79
|
+
|
|
80
|
+
#table => Object
|
|
81
|
+
|
|
82
|
+
Creating a new item
|
|
83
|
+
|
|
84
|
+
Description: Inserts a new item
|
|
85
|
+
Input: Store
|
|
86
|
+
Output: Aws::DynamoDB::Types::PutItemOutput
|
|
87
|
+
|
|
88
|
+
#put_store => Object
|
|
89
|
+
|
|
90
|
+
Querying stores
|
|
91
|
+
|
|
92
|
+
Description: Look for stores dependent on the input Lat, Long (as described above)
|
|
93
|
+
Input: Store
|
|
94
|
+
Output: Array[Store]
|
|
95
|
+
|
|
96
|
+
#get_stores => Array[Store]
|
|
97
|
+
|
|
98
|
+
### Store
|
|
99
|
+
|
|
100
|
+
**Methods**
|
|
101
|
+
Initialization
|
|
102
|
+
|
|
103
|
+
Description: Initialization
|
|
104
|
+
Input: Hash => {
|
|
105
|
+
latitude # Required
|
|
106
|
+
longitude # Required
|
|
107
|
+
address
|
|
108
|
+
city
|
|
109
|
+
state
|
|
110
|
+
zip
|
|
111
|
+
area_code
|
|
112
|
+
phone
|
|
113
|
+
name
|
|
114
|
+
geohash # Calculated based on lat,long if not provided
|
|
115
|
+
}
|
|
116
|
+
Output: Store
|
|
117
|
+
|
|
118
|
+
#new => Store
|
|
119
|
+
|
|
120
|
+
### DynamodbGeo
|
|
121
|
+
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
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
## Geohashing
|
|
5
125
|
Includes a Geohash implimentation written in C
|
|
6
126
|
<https://github.com/simplegeo/libgeohash>
|
|
7
127
|
|
|
@@ -43,6 +163,19 @@ Viewing all my neighbours
|
|
|
43
163
|
|
|
44
164
|
Geohash.neighbours(hash) => Array[Geohash]
|
|
45
165
|
|
|
166
|
+
Viewing one of my neighbours
|
|
167
|
+
|
|
168
|
+
Description: Takes in a Geohash and shows the neighbour in the cardinal direction
|
|
169
|
+
NORTH = 0
|
|
170
|
+
EAST = 1
|
|
171
|
+
SOUTH = 2
|
|
172
|
+
WEST = 3
|
|
173
|
+
Input: Geohash => String
|
|
174
|
+
Direction => Integer
|
|
175
|
+
Output: Geohash
|
|
176
|
+
|
|
177
|
+
Geohash.neighbour(hash) => Geohash
|
|
178
|
+
|
|
46
179
|
Get width and height about a specific precision
|
|
47
180
|
|
|
48
181
|
Description: Takes in a precision value, returns the height and width of the box
|
|
@@ -51,5 +184,6 @@ Get width and height about a specific precision
|
|
|
51
184
|
|
|
52
185
|
Geohash.dimensions(precision) => Dimension
|
|
53
186
|
|
|
187
|
+
### Objects
|
|
54
188
|
#### Geocoord(Object) => attr_accessor: :latitude, :longitude, :north, :south, :east, :west, :dimension
|
|
55
189
|
#### 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,15 @@
|
|
|
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')
|
|
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
|
+
)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/dynamodb_geo/version.rb
CHANGED
|
@@ -0,0 +1,136 @@
|
|
|
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')
|
|
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
|
+
@client = Aws::DynamoDB::Client.new(
|
|
27
|
+
region: region,
|
|
28
|
+
credentials: credentials,
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def table
|
|
33
|
+
create_table unless @client.list_tables.table_names.include?(@table_name)
|
|
34
|
+
|
|
35
|
+
@client.describe_table(table_name: @table_name)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def put_store(store)
|
|
39
|
+
hash = store.geohash[0..(@local_area_size - 1)]
|
|
40
|
+
json = {
|
|
41
|
+
latitude: store.lat,
|
|
42
|
+
longitude: store.long,
|
|
43
|
+
address: store.address,
|
|
44
|
+
city: store.city,
|
|
45
|
+
state: store.state,
|
|
46
|
+
zip: store.zip,
|
|
47
|
+
area_code: store.area_code,
|
|
48
|
+
phone: store.phone,
|
|
49
|
+
name: store.name,
|
|
50
|
+
}
|
|
51
|
+
put_point(hash, json)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def get_stores(lat, long)
|
|
55
|
+
geohash = Geohash.encode(lat, long, @local_area_size)
|
|
56
|
+
hash = geohash[0..(@hash_key_length - 1)]
|
|
57
|
+
all_stores = []
|
|
58
|
+
neighbours = Geohash.neighbours(hash)
|
|
59
|
+
neighbours.unshift(hash)
|
|
60
|
+
|
|
61
|
+
neighbours.each do |neighbour|
|
|
62
|
+
resp = query(neighbour)
|
|
63
|
+
resp.items.each do |item|
|
|
64
|
+
all_stores << Store.new(item['geoJson'], item['geohash'])
|
|
65
|
+
end
|
|
66
|
+
break if all_stores.length >= max_item_return
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# We got all the stores in the biggest possible area, we increase the hash by one and search around now
|
|
70
|
+
neighbours = Geohash.neighbours(geohash)
|
|
71
|
+
|
|
72
|
+
closest_stores = all_stores.select { |store| store.geohash == geohash }
|
|
73
|
+
surrounding_stores = (all_stores - closest_stores).select { |store| neighbours.include?(store.geohash) }
|
|
74
|
+
remaining_stores = all_stores - (closest_stores + surrounding_stores)
|
|
75
|
+
|
|
76
|
+
return closest_stores + surrounding_stores + remaining_stores
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def query(hash)
|
|
82
|
+
client.query({
|
|
83
|
+
table_name: @table_name,
|
|
84
|
+
index_name: @geohash_index,
|
|
85
|
+
expression_attribute_values: {
|
|
86
|
+
':hash' => hash,
|
|
87
|
+
},
|
|
88
|
+
key_condition_expression: "#{@hash_key} = :hash",
|
|
89
|
+
})
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def put_point(hash, json)
|
|
93
|
+
uuid = SecureRandom.uuid
|
|
94
|
+
|
|
95
|
+
@client.put_item({
|
|
96
|
+
table_name: @table_name,
|
|
97
|
+
item: {
|
|
98
|
+
@hash_key => hash[0..(@hash_key_length - 1)],
|
|
99
|
+
@range_key => uuid,
|
|
100
|
+
@geohash_key => hash,
|
|
101
|
+
@geojson => json
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def create_table
|
|
107
|
+
@client.create_table({
|
|
108
|
+
attribute_definitions: [
|
|
109
|
+
{ attribute_name: @hash_key, attribute_type: 'S' },
|
|
110
|
+
{ attribute_name: @range_key, attribute_type: 'S' },
|
|
111
|
+
{ attribute_name: @geohash_key, attribute_type: 'S' }
|
|
112
|
+
],
|
|
113
|
+
key_schema: [
|
|
114
|
+
{ attribute_name: @hash_key, key_type: 'HASH' },
|
|
115
|
+
{ attribute_name: @range_key, key_type: 'RANGE' }
|
|
116
|
+
],
|
|
117
|
+
local_secondary_indexes: [
|
|
118
|
+
{
|
|
119
|
+
index_name: @geohash_index,
|
|
120
|
+
key_schema: [
|
|
121
|
+
{ attribute_name: @hash_key, key_type: 'HASH' },
|
|
122
|
+
{ attribute_name: @geohash_key, key_type: 'RANGE' }
|
|
123
|
+
],
|
|
124
|
+
projection: {
|
|
125
|
+
projection_type: "ALL"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
provisioned_throughput: {
|
|
130
|
+
read_capacity_units: 10,
|
|
131
|
+
write_capacity_units: 5,
|
|
132
|
+
},
|
|
133
|
+
table_name: @table_name
|
|
134
|
+
})
|
|
135
|
+
end
|
|
136
|
+
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
|
+
debugger;1
|
|
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.0
|
|
4
|
+
version: 0.1.0
|
|
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.0
|
|
130
|
+
summary: dynamodb_geo-0.1.0
|
|
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'
|