activerecord-postgres-earthdistance 0.4.4 → 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/.rubocop.yml +20 -0
- data/Gemfile.lock +20 -12
- data/README.md +22 -9
- data/Rakefile +10 -11
- data/activerecord-postgres-earthdistance.gemspec +12 -5
- data/lib/activerecord-postgres-earthdistance.rb +1 -1
- data/lib/activerecord-postgres-earthdistance/activerecord.rb +5 -6
- data/lib/activerecord-postgres-earthdistance/acts_as_geolocated.rb +64 -25
- data/lib/activerecord-postgres-earthdistance/railties.rb +8 -10
- data/spec/act_as_geolocated_spec.rb +101 -39
- data/spec/fixtures/job.rb +4 -0
- data/spec/spec_helper.rb +31 -22
- metadata +21 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 837c44a62054d3207412a8426a108d91c3ee565a
|
4
|
+
data.tar.gz: 51eb68df69f6259f9ed85cfa01a8b699bdfdc59d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc1e1bb9e5ee4f5abf5d282cc0580ddde5994a7011e0948413b1191549fe78850835eb9aee996fa4a5faa12534124848371c327e82a0b36e24f07d934881f86d
|
7
|
+
data.tar.gz: b0a529f93d2adcba785c74c7440ac7ef45eae07175b7ac7a670e388046dc589c6082c9dc63b0d698c7070d97d91cfb3da8ae61afab4a1531151090341f3711ee
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Metrics/LineLength:
|
2
|
+
Max: 100
|
3
|
+
|
4
|
+
Metrics/BlockLength:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
Metrics/MethodLength:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Style/Documentation:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Style/FileName:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Style/StringLiterals:
|
17
|
+
EnforcedStyle: double_quotes
|
18
|
+
|
19
|
+
Style/VariableNumber:
|
20
|
+
EnforcedStyle: normalcase
|
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.5.0)
|
5
5
|
activerecord (>= 3.1)
|
6
6
|
pg
|
7
7
|
rake
|
@@ -9,25 +9,31 @@ PATH
|
|
9
9
|
GEM
|
10
10
|
remote: http://rubygems.org/
|
11
11
|
specs:
|
12
|
-
activemodel (5.0.0)
|
13
|
-
activesupport (= 5.0.0)
|
14
|
-
activerecord (5.0.0)
|
15
|
-
activemodel (= 5.0.0)
|
16
|
-
activesupport (= 5.0.0)
|
12
|
+
activemodel (5.0.0.1)
|
13
|
+
activesupport (= 5.0.0.1)
|
14
|
+
activerecord (5.0.0.1)
|
15
|
+
activemodel (= 5.0.0.1)
|
16
|
+
activesupport (= 5.0.0.1)
|
17
17
|
arel (~> 7.0)
|
18
|
-
activesupport (5.0.0)
|
18
|
+
activesupport (5.0.0.1)
|
19
19
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
20
20
|
i18n (~> 0.7)
|
21
21
|
minitest (~> 5.1)
|
22
22
|
tzinfo (~> 1.1)
|
23
|
-
arel (7.1.
|
23
|
+
arel (7.1.4)
|
24
|
+
coderay (1.1.1)
|
24
25
|
concurrent-ruby (1.0.2)
|
25
26
|
diff-lcs (1.2.5)
|
26
27
|
i18n (0.7.0)
|
27
28
|
json (1.8.3)
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
method_source (0.8.2)
|
30
|
+
minitest (5.9.1)
|
31
|
+
pg (0.19.0)
|
32
|
+
pry (0.10.4)
|
33
|
+
coderay (~> 1.1.0)
|
34
|
+
method_source (~> 0.8.1)
|
35
|
+
slop (~> 3.4)
|
36
|
+
rake (11.3.0)
|
31
37
|
rdoc (4.2.1)
|
32
38
|
json (~> 1.4)
|
33
39
|
rspec (2.99.0)
|
@@ -38,6 +44,7 @@ GEM
|
|
38
44
|
rspec-expectations (2.99.2)
|
39
45
|
diff-lcs (>= 1.1.3, < 2.0)
|
40
46
|
rspec-mocks (2.99.4)
|
47
|
+
slop (3.6.0)
|
41
48
|
thread_safe (0.3.5)
|
42
49
|
tzinfo (1.2.2)
|
43
50
|
thread_safe (~> 0.1)
|
@@ -48,8 +55,9 @@ PLATFORMS
|
|
48
55
|
DEPENDENCIES
|
49
56
|
activerecord-postgres-earthdistance!
|
50
57
|
bundler
|
58
|
+
pry
|
51
59
|
rdoc
|
52
60
|
rspec (~> 2.11)
|
53
61
|
|
54
62
|
BUNDLED WITH
|
55
|
-
1.
|
63
|
+
1.13.1
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
#ActiveRecord + PostgreSQL Earthdistance [](https://travis-ci.org/diogob/activerecord-postgres-earthdistance)
|
1
|
+
# ActiveRecord + PostgreSQL Earthdistance [](https://travis-ci.org/diogob/activerecord-postgres-earthdistance) [](https://codeclimate.com/github/diogob/activerecord-postgres-earthdistance)
|
2
2
|
|
3
3
|
Check distances with latitude and longitude using PostgreSQL special indexes.
|
4
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
|
-
##Requirements
|
6
|
+
## Requirements
|
7
7
|
|
8
8
|
Postgresql 9.1+ with contrib and Rails 3.1+
|
9
9
|
On Ubuntu, this is easy: `sudo apt-get install postgresql-contrib-9.1`
|
@@ -14,7 +14,7 @@ On Mac you have a couple of options:
|
|
14
14
|
* [Homebrew’s](https://github.com/mxcl/homebrew) Postgres installation also includes the contrib packages: `brew install postgres`
|
15
15
|
* [Postgres.app](http://postgresapp.com/)
|
16
16
|
|
17
|
-
##Install
|
17
|
+
## Install
|
18
18
|
|
19
19
|
|
20
20
|
Earthdistance is a PostgreSQL contrib module, [check it out first](http://www.postgresql.org/docs/9.2/static/earthdistance.html).
|
@@ -60,7 +60,7 @@ This will create the index with a SQL like this:
|
|
60
60
|
CREATE INDEX places_earthdistance_ix ON places USING GIST (ll_to_earth(lat, lng));
|
61
61
|
```
|
62
62
|
|
63
|
-
##Usage
|
63
|
+
## Usage
|
64
64
|
|
65
65
|
This gem only provides a custom serialization coder.
|
66
66
|
If you want to use it just put in your Gemfile:
|
@@ -86,7 +86,15 @@ class Place < ActiveRecord::Base
|
|
86
86
|
end
|
87
87
|
```
|
88
88
|
|
89
|
-
|
89
|
+
You can also locale other entities through an geolocated association as in:
|
90
|
+
```ruby
|
91
|
+
class Job < ActiveRecord::Base
|
92
|
+
belongs_to :job
|
93
|
+
acts_as_geolocated through: :job
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
### Querying the database
|
90
98
|
|
91
99
|
To query for all places within a given radius of 100 meters from the origin -22.951916,-43.210487 just use:
|
92
100
|
```ruby
|
@@ -98,6 +106,11 @@ You can also order the records based on the distance from a point
|
|
98
106
|
Place.within_radius(100, -22.951916,-43.210487).order_by_distance(-22.951916,-43.210487)
|
99
107
|
```
|
100
108
|
|
109
|
+
To query on associated models (the joins will be included for you):
|
110
|
+
```ruby
|
111
|
+
Job.within_radius(100, -22.951916,-43.210487)
|
112
|
+
```
|
113
|
+
|
101
114
|
The `within_radius` query performs two checks: first against the *bounding box*, followed by computing the exact distance for
|
102
115
|
all contained elements. The latter might be computationally expensive for big ranges.
|
103
116
|
So if precision is not an issue but query speed is, you might want to query against the bounding box only:
|
@@ -112,7 +125,7 @@ closest = Place.within_radius(100, *point).order_by_distance(*point).selecting_d
|
|
112
125
|
closest.distance
|
113
126
|
```
|
114
127
|
|
115
|
-
##Test Database
|
128
|
+
## Test Database
|
116
129
|
|
117
130
|
To have earthdistance enabled when you load your database schema (as happens in rake db:test:prepare), you
|
118
131
|
have two options.
|
@@ -128,12 +141,12 @@ This will change your schema dumps from Ruby to SQL. If you're
|
|
128
141
|
unsure about the implications of this change, we suggest reading this
|
129
142
|
[Rails Guide](http://guides.rubyonrails.org/migrations.html#schema-dumping-and-you).
|
130
143
|
|
131
|
-
##Help
|
144
|
+
## Help
|
132
145
|
|
133
146
|
You can use issues in github for that. Or else you can reach us at
|
134
147
|
twitter: [@dbiazus](https://twitter.com/#!/dbiazus)
|
135
148
|
|
136
|
-
##Note on Patches/Pull Requests
|
149
|
+
## Note on Patches/Pull Requests
|
137
150
|
|
138
151
|
|
139
152
|
* Fork the project.
|
@@ -142,6 +155,6 @@ twitter: [@dbiazus](https://twitter.com/#!/dbiazus)
|
|
142
155
|
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
143
156
|
* Send me a pull request. Bonus points for topic branches.
|
144
157
|
|
145
|
-
##Copyright
|
158
|
+
## Copyright
|
146
159
|
|
147
160
|
Copyright © 2010 Diogo Biazus. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rubygems"
|
5
|
+
require "rspec/core/rake_task"
|
6
|
+
require "rdoc/task"
|
7
7
|
|
8
|
-
task :
|
8
|
+
task default: :spec
|
9
9
|
|
10
10
|
begin
|
11
11
|
Bundler.setup(:default, :development)
|
@@ -18,10 +18,9 @@ end
|
|
18
18
|
RSpec::Core::RakeTask.new(:spec)
|
19
19
|
|
20
20
|
RDoc::Task.new do |rdoc|
|
21
|
-
version = File.exist?(
|
22
|
-
rdoc.rdoc_dir =
|
21
|
+
version = File.exist?("VERSION") ? File.read("VERSION") : ""
|
22
|
+
rdoc.rdoc_dir = "rdoc"
|
23
23
|
rdoc.title = "activerecord-postgres-hstore #{version}"
|
24
|
-
rdoc.rdoc_files.include(
|
25
|
-
rdoc.rdoc_files.include(
|
24
|
+
rdoc.rdoc_files.include("README*")
|
25
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
26
26
|
end
|
27
|
-
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
lib = File.expand_path(
|
3
|
-
|
2
|
+
lib = File.expand_path("../lib/", __FILE__)
|
3
|
+
$LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "activerecord-postgres-earthdistance"
|
7
|
-
s.version = "0.
|
7
|
+
s.version = "0.5.0"
|
8
8
|
|
9
9
|
s.platform = Gem::Platform::RUBY
|
10
10
|
s.license = "MIT"
|
@@ -12,7 +12,9 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.email = "diogo@biazus.me"
|
13
13
|
s.homepage = "http://github.com/diogob/activerecord-postgres-earthdistance"
|
14
14
|
s.summary = "Check distances with latitude and longitude using PostgreSQL special indexes"
|
15
|
-
s.description = "This gem enables your model to query the database using the earthdistance
|
15
|
+
s.description = "This gem enables your model to query the database using the earthdistance \
|
16
|
+
extension. This should be much faster than using trigonometry functions over\
|
17
|
+
standart indexs."
|
16
18
|
s.required_ruby_version = ">= 1.8.7"
|
17
19
|
s.required_rubygems_version = ">= 1.3.6"
|
18
20
|
|
@@ -22,8 +24,13 @@ Gem::Specification.new do |s|
|
|
22
24
|
s.add_development_dependency "bundler"
|
23
25
|
s.add_development_dependency "rdoc"
|
24
26
|
s.add_development_dependency "rspec", "~> 2.11"
|
27
|
+
s.add_development_dependency "pry"
|
25
28
|
|
26
|
-
git_files =
|
29
|
+
git_files = begin
|
30
|
+
`git ls-files`.split("\n")
|
31
|
+
rescue
|
32
|
+
""
|
33
|
+
end
|
27
34
|
s.files = git_files
|
28
35
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
29
36
|
s.executables = []
|
@@ -3,14 +3,13 @@ require "activerecord-postgres-earthdistance/acts_as_geolocated"
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
5
|
module SchemaStatements
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
[table_name, table_name, (options[:lat] || 'lat'), (options[:lng] || 'lng')]
|
6
|
+
def add_earthdistance_index(table_name, options = {})
|
7
|
+
execute("CREATE INDEX %s_earthdistance_ix ON %s USING gist (ll_to_earth(%s, %s));")
|
8
|
+
.format([table_name, table_name, (options[:lat] || "lat"), (options[:lng] || "lng")])
|
10
9
|
end
|
11
10
|
|
12
|
-
def remove_earthdistance_index
|
13
|
-
execute
|
11
|
+
def remove_earthdistance_index(table_name)
|
12
|
+
execute("DROP INDEX %s_earthdistance_ix;").format([table_name])
|
14
13
|
end
|
15
14
|
end
|
16
15
|
end
|
@@ -4,57 +4,96 @@ module ActiveRecordPostgresEarthdistance
|
|
4
4
|
|
5
5
|
module ClassMethods
|
6
6
|
def acts_as_geolocated(options = {})
|
7
|
-
cattr_accessor :latitude_column, :longitude_column
|
7
|
+
cattr_accessor :latitude_column, :longitude_column, :through_table
|
8
8
|
self.latitude_column = options[:lat] || (column_names.include?("lat") ? "lat" : "latitude")
|
9
|
-
self.longitude_column = options[:lng] ||
|
9
|
+
self.longitude_column = options[:lng] ||
|
10
|
+
(column_names.include?("lng") ? "lng" : "longitude")
|
11
|
+
self.through_table = options[:through]
|
10
12
|
end
|
11
13
|
|
12
14
|
def within_box(radius, lat, lng)
|
13
|
-
earth_box = Arel::Nodes::NamedFunction.new(
|
14
|
-
|
15
|
+
earth_box = Arel::Nodes::NamedFunction.new(
|
16
|
+
"earth_box",
|
17
|
+
[Utils.ll_to_earth_coords(lat, lng), Utils.quote_value(radius)]
|
18
|
+
)
|
19
|
+
joins(through_table)
|
20
|
+
.where(
|
21
|
+
Arel::Nodes::InfixOperation.new(
|
22
|
+
"<@",
|
23
|
+
Utils.ll_to_earth_columns(through_table_klass),
|
24
|
+
earth_box
|
25
|
+
)
|
26
|
+
)
|
15
27
|
end
|
16
28
|
|
17
29
|
def within_radius(radius, lat, lng)
|
18
|
-
earth_distance =
|
19
|
-
within_box(radius, lat, lng)
|
30
|
+
earth_distance = Utils.earth_distance(through_table_klass, lat, lng)
|
31
|
+
within_box(radius, lat, lng)
|
32
|
+
.where(Arel::Nodes::InfixOperation.new("<=", earth_distance, Utils.quote_value(radius)))
|
20
33
|
end
|
21
34
|
|
22
35
|
def order_by_distance(lat, lng, order = "ASC")
|
23
|
-
earth_distance =
|
24
|
-
order("#{earth_distance.to_sql} #{order
|
36
|
+
earth_distance = Utils.earth_distance(through_table_klass, lat, lng)
|
37
|
+
joins(through_table).order("#{earth_distance.to_sql} #{order}")
|
25
38
|
end
|
26
|
-
end
|
27
39
|
|
28
|
-
|
29
|
-
def self.ll_to_earth_columns(klass)
|
30
|
-
Arel::Nodes::NamedFunction.new('ll_to_earth', [klass.arel_table[klass.latitude_column], klass.arel_table[klass.longitude_column]])
|
31
|
-
end
|
40
|
+
private
|
32
41
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
def self.quote_value value
|
38
|
-
if Arel::Nodes.respond_to?(:build_quoted) # for arel >= 6.0.0
|
39
|
-
Arel::Nodes.build_quoted(value)
|
42
|
+
def through_table_klass
|
43
|
+
if through_table.present?
|
44
|
+
reflections[through_table.to_s].klass
|
40
45
|
else
|
41
|
-
|
46
|
+
self
|
42
47
|
end
|
43
48
|
end
|
44
49
|
end
|
45
50
|
end
|
46
51
|
|
52
|
+
module Utils
|
53
|
+
def self.earth_distance(through_table_klass, lat, lng, aliaz = nil)
|
54
|
+
Arel::Nodes::NamedFunction.new(
|
55
|
+
"earth_distance",
|
56
|
+
[
|
57
|
+
ll_to_earth_columns(through_table_klass),
|
58
|
+
ll_to_earth_coords(lat, lng)
|
59
|
+
],
|
60
|
+
aliaz
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.ll_to_earth_columns(klass)
|
65
|
+
Arel::Nodes::NamedFunction.new(
|
66
|
+
"ll_to_earth",
|
67
|
+
[klass.arel_table[klass.latitude_column], klass.arel_table[klass.longitude_column]]
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.ll_to_earth_coords(lat, lng)
|
72
|
+
Arel::Nodes::NamedFunction.new("ll_to_earth", [quote_value(lat), quote_value(lng)])
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.quote_value(value)
|
76
|
+
if Arel::Nodes.respond_to?(:build_quoted) # for arel >= 6.0.0
|
77
|
+
Arel::Nodes.build_quoted(value)
|
78
|
+
else
|
79
|
+
value
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
47
84
|
module QueryMethods
|
48
|
-
def selecting_distance_from
|
85
|
+
def selecting_distance_from(lat, lng, name = "distance", include_default_columns = true)
|
49
86
|
clone.tap do |relation|
|
50
87
|
values = []
|
51
|
-
|
52
|
-
|
88
|
+
if relation.select_values.empty? && include_default_columns
|
89
|
+
values << relation.arel_table[Arel.star]
|
90
|
+
end
|
91
|
+
values << Utils.earth_distance(self, lat, lng, name)
|
92
|
+
|
53
93
|
relation.select_values = values
|
54
94
|
end
|
55
95
|
end
|
56
96
|
end
|
57
|
-
|
58
97
|
end
|
59
98
|
|
60
99
|
ActiveRecord::Base.send :include, ActiveRecordPostgresEarthdistance::ActsAsGeolocated
|
@@ -1,13 +1,13 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "rails"
|
2
|
+
require "rails/generators"
|
3
|
+
require "rails/generators/migration"
|
4
|
+
require "active_record"
|
5
5
|
# = Earth Distance Railtie
|
6
6
|
#
|
7
7
|
# Creates a new railtie for 2 reasons:
|
8
8
|
#
|
9
9
|
# * Initialize ActiveRecord properly
|
10
|
-
# * Add earthdistance:setup generator
|
10
|
+
# * Add earthdistance:setup generator
|
11
11
|
class EarthDistance < Rails::Railtie
|
12
12
|
# Creates the earthdistance:setup generator. This generator creates a migration that
|
13
13
|
# adds earthdistance support for your database. If fact, it's just the sql from the
|
@@ -20,21 +20,19 @@ class EarthDistance < Rails::Railtie
|
|
20
20
|
include Rails::Generators::Migration
|
21
21
|
|
22
22
|
def self.source_root
|
23
|
-
@source_root ||= File.join(File.dirname(__FILE__),
|
23
|
+
@source_root ||= File.join(File.dirname(__FILE__), "..", "templates")
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.next_migration_number(dirname)
|
27
27
|
if ActiveRecord::Base.timestamped_migrations
|
28
28
|
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
29
29
|
else
|
30
|
-
"%.3d"
|
30
|
+
"%.3d".format(current_migration_number(dirname) + 1)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
def create_migration_file
|
35
|
-
migration_template
|
35
|
+
migration_template "setup_earthdistance.rb", "db/migrate/setup_earthdistance.rb"
|
36
36
|
end
|
37
|
-
|
38
37
|
end
|
39
38
|
end
|
40
|
-
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe "ActiveRecord::Base.act_as_geolocated" do
|
4
|
-
describe
|
4
|
+
describe "ActiveRecord::Base" do
|
5
5
|
context "when using .where with a model instance as a placeholder" do
|
6
6
|
let(:place) { Place.create! }
|
7
|
-
subject { Place.where(
|
7
|
+
subject { Place.where("id = ?", place).first }
|
8
8
|
after { place.destroy! }
|
9
9
|
|
10
10
|
it { should == place }
|
@@ -16,7 +16,7 @@ describe "ActiveRecord::Base.act_as_geolocated" do
|
|
16
16
|
|
17
17
|
subject { Place.within_box(test_data[:radius], test_data[:lat], test_data[:lng]) }
|
18
18
|
|
19
|
-
before(:all) { @place = Place.create!(:
|
19
|
+
before(:all) { @place = Place.create!(lat: -30.0277041, lng: -51.2287346) }
|
20
20
|
after(:all) { @place.destroy }
|
21
21
|
|
22
22
|
context "when query with null data" do
|
@@ -24,19 +24,19 @@ describe "ActiveRecord::Base.act_as_geolocated" do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
context "when query for the exact same point with radius 0" do
|
27
|
-
let(:test_data) { { lat: -30.0277041, lng: -51.2287346
|
27
|
+
let(:test_data) { { lat: -30.0277041, lng: -51.2287346, radius: 0 } }
|
28
28
|
|
29
29
|
it { should == [@place] }
|
30
30
|
end
|
31
31
|
|
32
32
|
context "when query for place within the box" do
|
33
|
-
let(:test_data) { { radius:
|
33
|
+
let(:test_data) { { radius: 4_000_000, lat: -27.5969039, lng: -48.5494544 } }
|
34
34
|
|
35
35
|
it { should == [@place] }
|
36
36
|
end
|
37
37
|
|
38
38
|
context "when query for place within the box, but outside the radius" do
|
39
|
-
let(:test_data) { { radius:
|
39
|
+
let(:test_data) { { radius: 300_000, lat: -27.5969039, lng: -48.5494544 } }
|
40
40
|
|
41
41
|
it "the place shouldn't be within the radius" do
|
42
42
|
Place.within_radius(test_data[:radius], test_data[:lat], test_data[:lng]).should be_empty
|
@@ -56,21 +56,28 @@ describe "ActiveRecord::Base.act_as_geolocated" do
|
|
56
56
|
subject { Place.within_box(test_data[:radius], test_data[:lat], test_data[:lng]) }
|
57
57
|
|
58
58
|
it "should work with objects having columns with the same name" do
|
59
|
-
expect
|
60
|
-
|
59
|
+
expect do
|
60
|
+
Place
|
61
|
+
.joins(:events)
|
62
|
+
.within_radius(test_data[:radius], test_data[:lat], test_data[:lng]).to_a
|
63
|
+
end.to_not raise_error
|
61
64
|
end
|
62
65
|
|
63
66
|
it "should work with nested associations" do
|
64
|
-
expect
|
67
|
+
expect do
|
68
|
+
Event
|
69
|
+
.joins(:events)
|
70
|
+
.within_radius(test_data[:radius], test_data[:lat], test_data[:lng]).to_a
|
71
|
+
end.to_not raise_error
|
65
72
|
end
|
66
73
|
end
|
67
74
|
end
|
68
75
|
|
69
76
|
describe "#within_radius" do
|
70
|
-
let(:test_data){ {lat: nil, lng: nil, radius: nil} }
|
71
|
-
subject{ Place.within_radius(test_data[:radius], test_data[:lat], test_data[:lng]) }
|
77
|
+
let(:test_data) { { lat: nil, lng: nil, radius: nil } }
|
78
|
+
subject { Place.within_radius(test_data[:radius], test_data[:lat], test_data[:lng]) }
|
72
79
|
before(:all) do
|
73
|
-
@place = Place.create!(:
|
80
|
+
@place = Place.create!(lat: -30.0277041, lng: -51.2287346)
|
74
81
|
end
|
75
82
|
|
76
83
|
after(:all) do
|
@@ -78,66 +85,121 @@ describe "ActiveRecord::Base.act_as_geolocated" do
|
|
78
85
|
end
|
79
86
|
|
80
87
|
context "when query with null data" do
|
81
|
-
it{ should == [] }
|
88
|
+
it { should == [] }
|
82
89
|
end
|
83
90
|
|
84
91
|
context "when query for the exact same point with radius 0" do
|
85
|
-
let(:test_data){{lat: -30.0277041, lng: -51.2287346
|
86
|
-
it{ should == [@place] }
|
92
|
+
let(:test_data) { { lat: -30.0277041, lng: -51.2287346, radius: 0 } }
|
93
|
+
it { should == [@place] }
|
87
94
|
end
|
88
95
|
|
89
96
|
context "when query for place within radius" do
|
90
|
-
let(:test_data){ {radius:
|
91
|
-
it{ should == [@place] }
|
97
|
+
let(:test_data) { { radius: 4_000_000, lat: -27.5969039, lng: -48.5494544 } }
|
98
|
+
it { should == [@place] }
|
92
99
|
end
|
93
100
|
|
94
101
|
context "when query for place outside the radius" do
|
95
|
-
let(:test_data){ {radius: 1000, lat: -27.5969039, lng: -48.5494544} }
|
96
|
-
it{ should == [] }
|
102
|
+
let(:test_data) { { radius: 1000, lat: -27.5969039, lng: -48.5494544 } }
|
103
|
+
it { should == [] }
|
104
|
+
end
|
105
|
+
|
106
|
+
context "uses lat and long of through table" do
|
107
|
+
subject do
|
108
|
+
Job.within_radius(test_data[:radius], test_data[:lat], test_data[:lng])
|
109
|
+
end
|
110
|
+
|
111
|
+
before(:all) do
|
112
|
+
@event = Event.create!(lat: -30.0277041, lng: -51.2287346)
|
113
|
+
@job = Job.create!(event: @event)
|
114
|
+
end
|
115
|
+
|
116
|
+
after(:all) do
|
117
|
+
@event.destroy
|
118
|
+
@job.destroy
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when query with null data" do
|
122
|
+
it { should == [] }
|
123
|
+
end
|
124
|
+
|
125
|
+
context "when query for the exact same point with radius 0" do
|
126
|
+
let(:test_data) { { lat: -30.0277041, lng: -51.2287346, radius: 0 } }
|
127
|
+
it { should == [@job] }
|
128
|
+
end
|
129
|
+
|
130
|
+
context "when query for place within radius" do
|
131
|
+
let(:test_data) { { radius: 4_000_000, lat: -27.5969039, lng: -48.5494544 } }
|
132
|
+
it { should == [@job] }
|
133
|
+
end
|
134
|
+
|
135
|
+
context "when query for place outside the radius" do
|
136
|
+
let(:test_data) { { radius: 1000, lat: -27.5969039, lng: -48.5494544 } }
|
137
|
+
it { should == [] }
|
138
|
+
end
|
97
139
|
end
|
98
140
|
end
|
99
141
|
|
100
142
|
describe "#order_by_distance" do
|
101
|
-
let(:current_location){ {lat: nil, lng: nil, radius: nil} }
|
102
|
-
|
143
|
+
let(:current_location) { { lat: nil, lng: nil, radius: nil } }
|
144
|
+
|
145
|
+
subject { Place.order_by_distance(current_location[:lat], current_location[:lng]) }
|
146
|
+
|
103
147
|
before(:all) do
|
104
|
-
@
|
105
|
-
@
|
148
|
+
@amsterdam = Place.create!(lat: 52.370216, lng: 4.895168)
|
149
|
+
@berlin = Place.create!(lat: 52.520007, lng: 13.404954) # Berlin
|
150
|
+
@event_in_amsterdam = Event.create!(lat: 52.370216, lng: 4.895168)
|
151
|
+
@event_in_berlin = Event.create!(lat: 52.520007, lng: 13.404954)
|
152
|
+
@amsterdam_job = Job.create!(event: @event_in_amsterdam)
|
153
|
+
@berlin_job = Job.create!(event: @event_in_berlin)
|
106
154
|
end
|
155
|
+
|
107
156
|
after(:all) do
|
108
|
-
@
|
109
|
-
@
|
157
|
+
@amsterdam.destroy
|
158
|
+
@berlin.destroy
|
159
|
+
@event_in_amsterdam.destroy
|
160
|
+
@event_in_berlin.destroy
|
161
|
+
@amsterdam_job.destroy
|
162
|
+
@berlin_job.destroy
|
163
|
+
end
|
164
|
+
|
165
|
+
context "uses lat and long of through table" do
|
166
|
+
subject do
|
167
|
+
Job.order_by_distance(current_location[:lat], current_location[:lng])
|
168
|
+
end
|
169
|
+
|
170
|
+
let(:current_location) { { lat: 51.511214, lng: 0.119824 } } # London
|
171
|
+
it { should == [@amsterdam_job, @berlin_job] }
|
110
172
|
end
|
111
173
|
|
112
174
|
context "when sorting on distance" do
|
113
|
-
let(:current_location){{lat: 51.511214, lng: 0.119824}} #London
|
114
|
-
it{ should == [@
|
175
|
+
let(:current_location) { { lat: 51.511214, lng: 0.119824 } } # London
|
176
|
+
it { should == [@amsterdam, @berlin] }
|
115
177
|
end
|
116
178
|
|
117
179
|
context "when sorting on distance from another location" do
|
118
|
-
let(:current_location){{lat: 52.229676, lng: 21.012229}} #Warsaw
|
119
|
-
it{ should == [@
|
180
|
+
let(:current_location) { { lat: 52.229676, lng: 21.012229 } } # Warsaw
|
181
|
+
it { should == [@berlin, @amsterdam] }
|
120
182
|
end
|
121
183
|
end
|
122
184
|
|
123
185
|
describe "#selecting_distance_from" do
|
124
|
-
let(:current_location){ {lat: nil, lng: nil, radius: nil} }
|
186
|
+
let(:current_location) { { lat: nil, lng: nil, radius: nil } }
|
125
187
|
subject do
|
126
|
-
Place
|
127
|
-
order_by_distance(current_location[:lat], current_location[:lng])
|
128
|
-
selecting_distance_from(current_location[:lat], current_location[:lng])
|
129
|
-
first
|
130
|
-
try{|p| [p.data, p.distance.to_f] }
|
188
|
+
Place
|
189
|
+
.order_by_distance(current_location[:lat], current_location[:lng])
|
190
|
+
.selecting_distance_from(current_location[:lat], current_location[:lng])
|
191
|
+
.first
|
192
|
+
.try { |p| [p.data, p.distance.to_f] }
|
131
193
|
end
|
132
194
|
before(:all) do
|
133
|
-
@place = Place.create!(:
|
195
|
+
@place = Place.create!(data: "Amsterdam", lat: 52.370216, lng: 4.895168) # Amsterdam
|
134
196
|
end
|
135
197
|
after(:all) do
|
136
198
|
@place.destroy
|
137
199
|
end
|
138
200
|
context "when selecting distance" do
|
139
|
-
let(:current_location){{lat: 52.229676, lng: 21.012229}} #Warsaw
|
140
|
-
it{ should == ["Amsterdam",
|
201
|
+
let(:current_location) { { lat: 52.229676, lng: 21.012229 } } # Warsaw
|
202
|
+
it { should == ["Amsterdam", 1_095_013.87438311] }
|
141
203
|
end
|
142
204
|
end
|
143
205
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__),
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
3
|
+
require "rspec"
|
4
|
+
require "rspec/autorun"
|
5
|
+
require "activerecord-postgres-earthdistance"
|
6
|
+
require "active_record"
|
7
7
|
|
8
8
|
RSpec.configure do |config|
|
9
9
|
config.before(:suite) do
|
@@ -11,12 +11,12 @@ RSpec.configure do |config|
|
|
11
11
|
# I do not use database users or password for the tests, using ident authentication instead
|
12
12
|
begin
|
13
13
|
ActiveRecord::Base.establish_connection(
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
14
|
+
adapter: "postgresql",
|
15
|
+
host: "localhost",
|
16
|
+
username: "postgres",
|
17
|
+
password: "postgres",
|
18
|
+
port: 5432,
|
19
|
+
database: "ar_pg_earthdistance_test"
|
20
20
|
)
|
21
21
|
ActiveRecord::Base.connection.execute %{
|
22
22
|
SET client_min_messages TO warning;
|
@@ -24,26 +24,35 @@ RSpec.configure do |config|
|
|
24
24
|
CREATE EXTENSION IF NOT EXISTS earthdistance;
|
25
25
|
DROP TABLE IF EXISTS places;
|
26
26
|
DROP TABLE IF EXISTS events;
|
27
|
+
DROP TABLE IF EXISTS jobs;
|
27
28
|
CREATE TABLE places (id serial PRIMARY KEY, data text, lat float8, lng float8);
|
28
|
-
CREATE TABLE events (
|
29
|
+
CREATE TABLE events (
|
30
|
+
id serial PRIMARY KEY,
|
31
|
+
event_id integer,
|
32
|
+
place_id integer,
|
33
|
+
data text,
|
34
|
+
lat float8,
|
35
|
+
lng float8
|
36
|
+
);
|
37
|
+
CREATE TABLE jobs (id serial PRIMARY KEY, event_id integer);
|
29
38
|
}
|
30
|
-
rescue
|
39
|
+
rescue StandardError => e
|
31
40
|
puts "Exception: #{e}"
|
32
41
|
ActiveRecord::Base.establish_connection(
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
36
|
-
:
|
37
|
-
:
|
38
|
-
:
|
42
|
+
adapter: "postgresql",
|
43
|
+
host: "localhost",
|
44
|
+
username: "postgres",
|
45
|
+
password: "postgres",
|
46
|
+
port: 5432,
|
47
|
+
database: "postgres"
|
39
48
|
)
|
40
49
|
ActiveRecord::Base.connection.execute "CREATE DATABASE ar_pg_earthdistance_test"
|
41
50
|
retry
|
42
51
|
end
|
43
52
|
|
44
53
|
# Load models used in spec
|
45
|
-
require
|
46
|
-
require
|
54
|
+
require "fixtures/place"
|
55
|
+
require "fixtures/event"
|
56
|
+
require "fixtures/job"
|
47
57
|
end
|
48
|
-
|
49
58
|
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.5.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: 2016-
|
11
|
+
date: 2016-11-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -94,8 +94,22 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '2.11'
|
97
|
-
|
98
|
-
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: This gem enables your model to query the database using the earthdistance extension.
|
112
|
+
This should be much faster than using trigonometry functions over standart
|
99
113
|
indexs.
|
100
114
|
email: diogo@biazus.me
|
101
115
|
executables: []
|
@@ -105,6 +119,7 @@ files:
|
|
105
119
|
- ".document"
|
106
120
|
- ".gitignore"
|
107
121
|
- ".rspec"
|
122
|
+
- ".rubocop.yml"
|
108
123
|
- ".travis.yml"
|
109
124
|
- Gemfile
|
110
125
|
- Gemfile.lock
|
@@ -121,6 +136,7 @@ files:
|
|
121
136
|
- lib/templates/setup_earthdistance.rb
|
122
137
|
- spec/act_as_geolocated_spec.rb
|
123
138
|
- spec/fixtures/event.rb
|
139
|
+
- spec/fixtures/job.rb
|
124
140
|
- spec/fixtures/place.rb
|
125
141
|
- spec/spec_helper.rb
|
126
142
|
homepage: http://github.com/diogob/activerecord-postgres-earthdistance
|
@@ -150,5 +166,6 @@ summary: Check distances with latitude and longitude using PostgreSQL special in
|
|
150
166
|
test_files:
|
151
167
|
- spec/act_as_geolocated_spec.rb
|
152
168
|
- spec/fixtures/event.rb
|
169
|
+
- spec/fixtures/job.rb
|
153
170
|
- spec/fixtures/place.rb
|
154
171
|
- spec/spec_helper.rb
|