activerecord-postgres-earthdistance 0.3.2 → 0.4.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/Gemfile.lock +61 -61
- data/README.md +19 -5
- data/activerecord-postgres-earthdistance.gemspec +1 -1
- data/lib/activerecord-postgres-earthdistance/acts_as_geolocated.rb +17 -3
- data/spec/act_as_geolocated_spec.rb +62 -0
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f9458af5bee1a6c5416b450109d62aa9888f37d7
|
|
4
|
+
data.tar.gz: 52a8f7eb26951d8c77f3b1332b630ed5978f560f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7e53a9aa32535c9ffd538d28221f99618f7497add3a8b6f4f63b38c4fee66e05feb6d0ae420c0ecec8bf8f4dbb7271564b586751a139c49be7f39d06e9e7642c
|
|
7
|
+
data.tar.gz: 895a6791fdd7d3a6ed3b73b70254a136cb119517f0dc5ba341c0e7a1f02aee61aa34d3915ee68412cfeaa06cc42a2c192d9bded4600e2fdb6edf2a12d2c382d5
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
activerecord-postgres-earthdistance (0.
|
|
4
|
+
activerecord-postgres-earthdistance (0.4.0)
|
|
5
5
|
pg
|
|
6
6
|
rails (>= 3.1)
|
|
7
7
|
rake
|
|
@@ -9,88 +9,88 @@ PATH
|
|
|
9
9
|
GEM
|
|
10
10
|
remote: http://rubygems.org/
|
|
11
11
|
specs:
|
|
12
|
-
actionmailer (4.
|
|
13
|
-
actionpack (= 4.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
actionmailer (4.1.8)
|
|
13
|
+
actionpack (= 4.1.8)
|
|
14
|
+
actionview (= 4.1.8)
|
|
15
|
+
mail (~> 2.5, >= 2.5.4)
|
|
16
|
+
actionpack (4.1.8)
|
|
17
|
+
actionview (= 4.1.8)
|
|
18
|
+
activesupport (= 4.1.8)
|
|
19
19
|
rack (~> 1.5.2)
|
|
20
20
|
rack-test (~> 0.6.2)
|
|
21
|
-
|
|
22
|
-
activesupport (= 4.
|
|
23
|
-
builder (~> 3.1
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
actionview (4.1.8)
|
|
22
|
+
activesupport (= 4.1.8)
|
|
23
|
+
builder (~> 3.1)
|
|
24
|
+
erubis (~> 2.7.0)
|
|
25
|
+
activemodel (4.1.8)
|
|
26
|
+
activesupport (= 4.1.8)
|
|
27
|
+
builder (~> 3.1)
|
|
28
|
+
activerecord (4.1.8)
|
|
29
|
+
activemodel (= 4.1.8)
|
|
30
|
+
activesupport (= 4.1.8)
|
|
31
|
+
arel (~> 5.0.0)
|
|
32
|
+
activesupport (4.1.8)
|
|
31
33
|
i18n (~> 0.6, >= 0.6.9)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
json (~> 1.7, >= 1.7.7)
|
|
35
|
+
minitest (~> 5.1)
|
|
34
36
|
thread_safe (~> 0.1)
|
|
35
|
-
tzinfo (~>
|
|
36
|
-
arel (
|
|
37
|
-
builder (3.
|
|
38
|
-
diff-lcs (1.
|
|
37
|
+
tzinfo (~> 1.1)
|
|
38
|
+
arel (5.0.1.20140414130214)
|
|
39
|
+
builder (3.2.2)
|
|
40
|
+
diff-lcs (1.2.5)
|
|
39
41
|
erubis (2.7.0)
|
|
40
42
|
hike (1.2.3)
|
|
41
|
-
i18n (0.6.
|
|
42
|
-
json (1.
|
|
43
|
-
mail (2.
|
|
44
|
-
mime-types (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
multi_json (1.9.2)
|
|
43
|
+
i18n (0.6.11)
|
|
44
|
+
json (1.8.1)
|
|
45
|
+
mail (2.6.3)
|
|
46
|
+
mime-types (>= 1.16, < 3)
|
|
47
|
+
mime-types (2.4.3)
|
|
48
|
+
minitest (5.4.3)
|
|
49
|
+
multi_json (1.10.1)
|
|
49
50
|
pg (0.17.1)
|
|
50
|
-
polyglot (0.3.4)
|
|
51
51
|
rack (1.5.2)
|
|
52
52
|
rack-test (0.6.2)
|
|
53
53
|
rack (>= 1.0)
|
|
54
|
-
rails (4.
|
|
55
|
-
actionmailer (= 4.
|
|
56
|
-
actionpack (= 4.
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
rails (4.1.8)
|
|
55
|
+
actionmailer (= 4.1.8)
|
|
56
|
+
actionpack (= 4.1.8)
|
|
57
|
+
actionview (= 4.1.8)
|
|
58
|
+
activemodel (= 4.1.8)
|
|
59
|
+
activerecord (= 4.1.8)
|
|
60
|
+
activesupport (= 4.1.8)
|
|
59
61
|
bundler (>= 1.3.0, < 2.0)
|
|
60
|
-
railties (= 4.
|
|
61
|
-
sprockets-rails (~> 2.0
|
|
62
|
-
railties (4.
|
|
63
|
-
actionpack (= 4.
|
|
64
|
-
activesupport (= 4.
|
|
62
|
+
railties (= 4.1.8)
|
|
63
|
+
sprockets-rails (~> 2.0)
|
|
64
|
+
railties (4.1.8)
|
|
65
|
+
actionpack (= 4.1.8)
|
|
66
|
+
activesupport (= 4.1.8)
|
|
65
67
|
rake (>= 0.8.7)
|
|
66
68
|
thor (>= 0.18.1, < 2.0)
|
|
67
|
-
rake (10.
|
|
68
|
-
rdoc (
|
|
69
|
+
rake (10.4.2)
|
|
70
|
+
rdoc (4.2.0)
|
|
69
71
|
json (~> 1.4)
|
|
70
|
-
rspec (2.
|
|
71
|
-
rspec-core (~> 2.
|
|
72
|
-
rspec-expectations (~> 2.
|
|
73
|
-
rspec-mocks (~> 2.
|
|
74
|
-
rspec-core (2.
|
|
75
|
-
rspec-expectations (2.
|
|
76
|
-
diff-lcs (
|
|
77
|
-
rspec-mocks (2.
|
|
78
|
-
sprockets (2.12.
|
|
72
|
+
rspec (2.99.0)
|
|
73
|
+
rspec-core (~> 2.99.0)
|
|
74
|
+
rspec-expectations (~> 2.99.0)
|
|
75
|
+
rspec-mocks (~> 2.99.0)
|
|
76
|
+
rspec-core (2.99.2)
|
|
77
|
+
rspec-expectations (2.99.2)
|
|
78
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
|
79
|
+
rspec-mocks (2.99.2)
|
|
80
|
+
sprockets (2.12.3)
|
|
79
81
|
hike (~> 1.2)
|
|
80
82
|
multi_json (~> 1.0)
|
|
81
83
|
rack (~> 1.0)
|
|
82
84
|
tilt (~> 1.1, != 1.3.0)
|
|
83
|
-
sprockets-rails (2.
|
|
85
|
+
sprockets-rails (2.2.2)
|
|
84
86
|
actionpack (>= 3.0)
|
|
85
87
|
activesupport (>= 3.0)
|
|
86
|
-
sprockets (
|
|
88
|
+
sprockets (>= 2.8, < 4.0)
|
|
87
89
|
thor (0.19.1)
|
|
88
|
-
thread_safe (0.3.
|
|
90
|
+
thread_safe (0.3.4)
|
|
89
91
|
tilt (1.4.1)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
polyglot (>= 0.3.1)
|
|
93
|
-
tzinfo (0.3.39)
|
|
92
|
+
tzinfo (1.2.2)
|
|
93
|
+
thread_safe (~> 0.1)
|
|
94
94
|
|
|
95
95
|
PLATFORMS
|
|
96
96
|
ruby
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#ActiveRecord + PostgreSQL Earthdistance [](https://travis-ci.org/diogob/activerecord-postgres-earthdistance)
|
|
2
2
|
|
|
3
3
|
Check distances with latitude and longitude using PostgreSQL special indexes.
|
|
4
|
-
This gem enables your model to query the database using the earthdistance extension. This should be much faster than using trigonometry functions over
|
|
4
|
+
This gem enables your model to query the database using the earthdistance extension. This should be much faster than using trigonometry functions over standard indexes.
|
|
5
5
|
|
|
6
6
|
##Requirements
|
|
7
7
|
|
|
@@ -30,7 +30,7 @@ And run your bundler:
|
|
|
30
30
|
Now you need to create a migration that adds earthdistance support for your
|
|
31
31
|
PostgreSQL database:
|
|
32
32
|
|
|
33
|
-
`rails g
|
|
33
|
+
`rails g earth_distance:setup`
|
|
34
34
|
|
|
35
35
|
Run it:
|
|
36
36
|
|
|
@@ -84,14 +84,28 @@ end
|
|
|
84
84
|
|
|
85
85
|
###Querying the database
|
|
86
86
|
|
|
87
|
-
To query for all places within a given radius of 100 meters from the origin
|
|
87
|
+
To query for all places within a given radius of 100 meters from the origin -22.951916,-43.210487 just use:
|
|
88
88
|
```ruby
|
|
89
|
-
Place.within_radius(
|
|
89
|
+
Place.within_radius(100, -22.951916, -43.210487).all
|
|
90
90
|
```
|
|
91
91
|
|
|
92
92
|
You can also order the records based on the distance from a point
|
|
93
93
|
```ruby
|
|
94
|
-
Place.within_radius(
|
|
94
|
+
Place.within_radius(100, -22.951916,-43.210487).order_by_distance(-22.951916,-43.210487)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The `within_radius` query performs two checks: first against the *bounding box*, followed by computing the exact distance for
|
|
98
|
+
all contained elements. The latter might be computationally expensive for big ranges.
|
|
99
|
+
So if precision is not an issue but query speed is, you might want to query against the bounding box only:
|
|
100
|
+
```ruby
|
|
101
|
+
Place.within_box(1_000_000, -22.951916,-43.210487)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Select the distance from a point:
|
|
105
|
+
```ruby
|
|
106
|
+
point = [-22.951916, -43.210487]
|
|
107
|
+
closest = Place.within_radius(100, *point).order_by_distance(*point).selecting_distance_from(*point).first
|
|
108
|
+
closest.distance
|
|
95
109
|
```
|
|
96
110
|
|
|
97
111
|
##Test Database
|
|
@@ -14,18 +14,32 @@ module ActiveRecordPostgresEarthdistance
|
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
def within_box radius, lat, lng
|
|
18
|
+
where("ll_to_earth(#{self.latitude_column}, #{self.longitude_column}) <@ earth_box(ll_to_earth(?, ?), ?)", lat, lng, radius)
|
|
19
|
+
end
|
|
20
|
+
|
|
17
21
|
def within_radius radius, lat, lng
|
|
18
|
-
where(
|
|
19
|
-
"AND earth_distance(ll_to_earth(#{self.latitude_column}, #{self.longitude_column}), ll_to_earth(?, ?)) <= ?",
|
|
20
|
-
lat, lng, radius, lat, lng, radius])
|
|
22
|
+
within_box(radius, lat, lng).where("earth_distance(ll_to_earth(#{self.latitude_column}, #{self.longitude_column}), ll_to_earth(?, ?)) <= ?", lat, lng, radius)
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def order_by_distance lat, lng, order= "ASC"
|
|
24
26
|
order("earth_distance(ll_to_earth(#{self.latitude_column}, #{self.longitude_column}), ll_to_earth(#{lat}, #{lng})) #{order}")
|
|
25
27
|
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
26
30
|
|
|
31
|
+
module QueryMethods
|
|
32
|
+
def selecting_distance_from lat, lng, name="distance", include_default_columns=true
|
|
33
|
+
clone.tap do |relation|
|
|
34
|
+
values = []
|
|
35
|
+
values << relation.arel_table[Arel.star] if relation.select_values.empty? && include_default_columns
|
|
36
|
+
values << "earth_distance(ll_to_earth(#{self.latitude_column}, #{self.longitude_column}), ll_to_earth(#{lat}, #{lng})) as #{name}"
|
|
37
|
+
relation.select_values = values
|
|
38
|
+
end
|
|
27
39
|
end
|
|
28
40
|
end
|
|
41
|
+
|
|
29
42
|
end
|
|
30
43
|
|
|
31
44
|
ActiveRecord::Base.send :include, ActiveRecordPostgresEarthdistance::ActsAsGeolocated
|
|
45
|
+
ActiveRecord::Relation.send :include, ActiveRecordPostgresEarthdistance::QueryMethods
|
|
@@ -1,6 +1,46 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe "ActiveRecord::Base.act_as_geolocated" do
|
|
4
|
+
describe "#within_box" do
|
|
5
|
+
let(:test_data) { { lat: nil, lng: nil, radius: nil } }
|
|
6
|
+
|
|
7
|
+
subject { Place.within_box(test_data[:radius], test_data[:lat], test_data[:lng]) }
|
|
8
|
+
|
|
9
|
+
before(:all) { @place = Place.create!(:lat => -30.0277041, :lng => -51.2287346) }
|
|
10
|
+
after(:all) { @place.destroy }
|
|
11
|
+
|
|
12
|
+
context "when query with null data" do
|
|
13
|
+
it { should be_empty }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "when query for the exact same point with radius 0" do
|
|
17
|
+
let(:test_data) { { lat: -30.0277041, lng: -51.2287346 , radius: 0 } }
|
|
18
|
+
|
|
19
|
+
it { should == [@place] }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "when query for place within the box" do
|
|
23
|
+
let(:test_data) { { radius: 4000000, lat: -27.5969039, lng: -48.5494544 } }
|
|
24
|
+
|
|
25
|
+
it { should == [@place] }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "when query for place within the box, but outside the radius" do
|
|
29
|
+
let(:test_data) { { radius: 300000, lat: -27.5969039, lng: -48.5494544 } }
|
|
30
|
+
|
|
31
|
+
it "the place shouldn't be within the radius" do
|
|
32
|
+
Place.within_radius(test_data[:radius], test_data[:lat], test_data[:lng]).should be_empty
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it { should == [@place] }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context "when query for place outside the box" do
|
|
39
|
+
let(:test_data) { { radius: 1000, lat: -27.5969039, lng: -48.5494544 } }
|
|
40
|
+
it { should be_empty }
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
4
44
|
describe "#within_radius" do
|
|
5
45
|
let(:test_data){ {lat: nil, lng: nil, radius: nil} }
|
|
6
46
|
subject{ Place.within_radius(test_data[:radius], test_data[:lat], test_data[:lng]) }
|
|
@@ -28,6 +68,7 @@ describe "ActiveRecord::Base.act_as_geolocated" do
|
|
|
28
68
|
|
|
29
69
|
context "when query for place outside the radius" do
|
|
30
70
|
let(:test_data){ {radius: 1000, lat: -27.5969039, lng: -48.5494544} }
|
|
71
|
+
it{ should == [] }
|
|
31
72
|
end
|
|
32
73
|
end
|
|
33
74
|
|
|
@@ -53,4 +94,25 @@ describe "ActiveRecord::Base.act_as_geolocated" do
|
|
|
53
94
|
it{ should == [@place_2, @place_1] }
|
|
54
95
|
end
|
|
55
96
|
end
|
|
97
|
+
|
|
98
|
+
describe "#selecting_distance_from" do
|
|
99
|
+
let(:current_location){ {lat: nil, lng: nil, radius: nil} }
|
|
100
|
+
subject do
|
|
101
|
+
Place.
|
|
102
|
+
order_by_distance(current_location[:lat], current_location[:lng]).
|
|
103
|
+
selecting_distance_from(current_location[:lat], current_location[:lng]).
|
|
104
|
+
first.
|
|
105
|
+
try{|p| [p.data, p.distance.to_f] }
|
|
106
|
+
end
|
|
107
|
+
before(:all) do
|
|
108
|
+
@place = Place.create!(:data => 'Amsterdam', :lat => 52.370216, :lng => 4.895168) #Amsterdam
|
|
109
|
+
end
|
|
110
|
+
after(:all) do
|
|
111
|
+
@place.destroy
|
|
112
|
+
end
|
|
113
|
+
context "when selecting distance" do
|
|
114
|
+
let(:current_location){{lat: 52.229676, lng: 21.012229}} #Warsaw
|
|
115
|
+
it{ should == ["Amsterdam", 1095013.87438311] }
|
|
116
|
+
end
|
|
117
|
+
end
|
|
56
118
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord-postgres-earthdistance
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Diogo Biazus
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-
|
|
11
|
+
date: 2014-12-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -142,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
142
142
|
version: 1.3.6
|
|
143
143
|
requirements: []
|
|
144
144
|
rubyforge_project:
|
|
145
|
-
rubygems_version: 2.2.
|
|
145
|
+
rubygems_version: 2.2.2
|
|
146
146
|
signing_key:
|
|
147
147
|
specification_version: 4
|
|
148
148
|
summary: Check distances with latitude and longitude using PostgreSQL special indexes
|