activerecord-postgres-earthdistance 0.5.2 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 94eb40debf0a4955024e1c8c4213b88530b294b1
4
- data.tar.gz: ec0ec0eb7d2472ebe8bad60197bbf0a7b45f1d36
2
+ SHA256:
3
+ metadata.gz: 14b64ce9adeedc19f81dcd2c359b11535643f2d40654dbb8577e3cde19246c5a
4
+ data.tar.gz: 146a8b1d02d23c2e53e12b26e7c97beff80a2adc4cdc8ffff677fbba77378c1a
5
5
  SHA512:
6
- metadata.gz: c9818e3e89ae5b0906c30fa097b26eb7445541541dbce5b31e633641f13d8a1ba797c500f4e420b0b6fad88315914e35c345971540043626ef1d1b589f5ecc35
7
- data.tar.gz: b6dfb3232de9828d812589a01a4f199ee36af6dbdda53064373253e5000370982465eec956f122e9efcdb3fdb9029f1c24e3e5cc820653146d01f56208ae5384
6
+ metadata.gz: e69b871105d854bae2e6b3595960af66970ca28451e85c664348b8802302db0cbb2b3f44047b302e181844d7da229522a800e533849698a51220794a717d8ad3
7
+ data.tar.gz: 599d73218999e4e6656b95ff2dacc7014e58d1afebb0d4e669a35aec584c43e101ad6e5593df8675523ac346f4887f67f0064c77a991b520d5e402b2a95b449c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- activerecord-postgres-earthdistance (0.5.2)
4
+ activerecord-postgres-earthdistance (0.7.1)
5
5
  activerecord (>= 3.1)
6
6
  pg
7
7
  rake
@@ -9,30 +9,31 @@ PATH
9
9
  GEM
10
10
  remote: http://rubygems.org/
11
11
  specs:
12
- activemodel (5.0.2)
13
- activesupport (= 5.0.2)
14
- activerecord (5.0.2)
15
- activemodel (= 5.0.2)
16
- activesupport (= 5.0.2)
17
- arel (~> 7.0)
18
- activesupport (5.0.2)
12
+ activemodel (5.2.1.1)
13
+ activesupport (= 5.2.1.1)
14
+ activerecord (5.2.1.1)
15
+ activemodel (= 5.2.1.1)
16
+ activesupport (= 5.2.1.1)
17
+ arel (>= 9.0)
18
+ activesupport (5.2.1.1)
19
19
  concurrent-ruby (~> 1.0, >= 1.0.2)
20
- i18n (~> 0.7)
20
+ i18n (>= 0.7, < 2)
21
21
  minitest (~> 5.1)
22
22
  tzinfo (~> 1.1)
23
- arel (7.1.4)
23
+ arel (9.0.0)
24
24
  coderay (1.1.1)
25
- concurrent-ruby (1.0.5)
25
+ concurrent-ruby (1.1.3)
26
26
  diff-lcs (1.3)
27
- i18n (0.8.1)
27
+ i18n (1.1.1)
28
+ concurrent-ruby (~> 1.0)
28
29
  method_source (0.8.2)
29
- minitest (5.10.1)
30
- pg (0.20.0)
30
+ minitest (5.11.3)
31
+ pg (1.1.3)
31
32
  pry (0.10.4)
32
33
  coderay (~> 1.1.0)
33
34
  method_source (~> 0.8.1)
34
35
  slop (~> 3.4)
35
- rake (12.0.0)
36
+ rake (12.3.1)
36
37
  rdoc (5.1.0)
37
38
  rspec (3.5.0)
38
39
  rspec-core (~> 3.5.0)
@@ -49,7 +50,7 @@ GEM
49
50
  rspec-support (3.5.0)
50
51
  slop (3.6.0)
51
52
  thread_safe (0.3.6)
52
- tzinfo (1.2.3)
53
+ tzinfo (1.2.5)
53
54
  thread_safe (~> 0.1)
54
55
 
55
56
  PLATFORMS
@@ -63,4 +64,4 @@ DEPENDENCIES
63
64
  rspec
64
65
 
65
66
  BUNDLED WITH
66
- 1.14.3
67
+ 1.16.3
@@ -4,7 +4,7 @@ $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.5.2"
7
+ s.version = "0.7.2"
8
8
 
9
9
  s.platform = Gem::Platform::RUBY
10
10
  s.license = "MIT"
@@ -1,17 +1,29 @@
1
1
  module ActiveRecordPostgresEarthdistance
2
+ MILES_TO_METERS_FACTOR = 1609.344
2
3
  module ActsAsGeolocated
3
4
  extend ActiveSupport::Concern
5
+
4
6
 
5
- module ClassMethods
7
+ module ClassMethods
6
8
  def acts_as_geolocated(options = {})
7
- cattr_accessor :latitude_column, :longitude_column, :through_table
8
- self.latitude_column = options[:lat] || (column_names.include?("lat") ? "lat" : "latitude")
9
- self.longitude_column = options[:lng] ||
10
- (column_names.include?("lng") ? "lng" : "longitude")
11
- self.through_table = options[:through]
9
+ begin
10
+ if table_exists?
11
+ cattr_accessor :latitude_column, :longitude_column, :through_table, :distance_unit
12
+ self.latitude_column = options[:lat] || (column_names.include?("lat") ? "lat" : "latitude")
13
+ self.longitude_column = options[:lng] ||
14
+ (column_names.include?("lng") ? "lng" : "longitude")
15
+ self.through_table = options[:through]
16
+ self.distance_unit = options[:distance_unit]
17
+ else
18
+ puts "[WARNING] table #{table_name} doesn't exist, acts_as_geolocated won't work. Skip this warning if you are running db migration"
19
+ end
20
+ rescue ActiveRecord::NoDatabaseError
21
+ rescue PG::ConnectionBad
22
+ end
12
23
  end
13
24
 
14
25
  def within_box(radius, lat, lng)
26
+ radius = radius.try(:*, MILES_TO_METERS_FACTOR) if distance_unit === :miles
15
27
  earth_box = Arel::Nodes::NamedFunction.new(
16
28
  "earth_box",
17
29
  [Utils.ll_to_earth_coords(lat, lng), Utils.quote_value(radius)]
@@ -27,6 +39,7 @@ module ActiveRecordPostgresEarthdistance
27
39
  end
28
40
 
29
41
  def within_radius(radius, lat, lng)
42
+ radius = radius.try(:*, MILES_TO_METERS_FACTOR) if distance_unit === :miles
30
43
  earth_distance = Utils.earth_distance(through_table_klass, lat, lng)
31
44
  within_box(radius, lat, lng)
32
45
  .where(Arel::Nodes::InfixOperation.new("<=", earth_distance, Utils.quote_value(radius)))
@@ -34,7 +47,7 @@ module ActiveRecordPostgresEarthdistance
34
47
 
35
48
  def order_by_distance(lat, lng, order = "ASC")
36
49
  earth_distance = Utils.earth_distance(through_table_klass, lat, lng)
37
- joins(through_table).order("#{earth_distance.to_sql} #{order}")
50
+ joins(through_table).order(Arel.sql("#{earth_distance.to_sql} #{order}"))
38
51
  end
39
52
 
40
53
  def through_table_klass
@@ -87,7 +100,12 @@ module ActiveRecordPostgresEarthdistance
87
100
  if relation.select_values.empty? && include_default_columns
88
101
  values << relation.arel_table[Arel.star]
89
102
  end
90
- values << Utils.earth_distance(through_table_klass, lat, lng, name)
103
+ distances = Utils.earth_distance(through_table_klass, lat, lng, name)
104
+ distances = Arel::Nodes::Multiplication.new(
105
+ Utils.quote_value(1 / MILES_TO_METERS_FACTOR), distances
106
+ ) if relation.distance_unit === :miles
107
+
108
+ values << distances
91
109
 
92
110
  relation.select_values = values
93
111
  end
@@ -32,7 +32,19 @@ class EarthDistance < Rails::Railtie
32
32
  end
33
33
 
34
34
  def create_migration_file
35
- migration_template "setup_earthdistance.rb", "db/migrate/setup_earthdistance.rb"
35
+ migration_template "setup_earthdistance.rb", "db/migrate/setup_earthdistance.rb", migration_version: migration_version
36
+ end
37
+
38
+ private
39
+
40
+ def requires_migration_version?
41
+ Rails::VERSION::MAJOR >= 5
42
+ end
43
+
44
+ def migration_version
45
+ if requires_migration_version?
46
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
47
+ end
36
48
  end
37
49
  end
38
50
  end
@@ -1,4 +1,4 @@
1
- class SetupEarthdistance < ActiveRecord::Migration
1
+ class SetupEarthdistance < ActiveRecord::Migration<%= migration_version %>
2
2
  def self.up
3
3
  execute "CREATE EXTENSION IF NOT EXISTS cube"
4
4
  execute "CREATE EXTENSION IF NOT EXISTS earthdistance"
@@ -73,6 +73,74 @@ describe "ActiveRecord::Base.act_as_geolocated" do
73
73
  end
74
74
  end
75
75
 
76
+ describe "#within_box with miles" do
77
+ let(:test_data) { { lat: nil, lng: nil, radius: nil } }
78
+
79
+ subject { Place.within_box(test_data[:radius], test_data[:lat], test_data[:lng]) }
80
+
81
+ before(:all) {
82
+ Place.acts_as_geolocated distance_unit: :miles
83
+ @place = Place.create!(lat: -30.0277041, lng: -51.2287346)
84
+ }
85
+ after(:all) {
86
+ Place.acts_as_geolocated
87
+ @place.destroy
88
+ }
89
+
90
+ context "when query with null data" do
91
+ it { is_expected.to be_empty }
92
+ end
93
+
94
+ context "when query for the exact same point with radius 0" do
95
+ let(:test_data) { { lat: -30.0277041, lng: -51.2287346, radius: 0 } }
96
+
97
+ it { is_expected.to eq [@place] }
98
+ end
99
+
100
+ context "when query for place within the box" do
101
+ let(:test_data) { { radius: 2400, lat: -27.5969039, lng: -48.5494544 } }
102
+
103
+ it { is_expected.to eq [@place] }
104
+ end
105
+
106
+ context "when query for place within the box, but outside the radius" do
107
+ let(:test_data) { { radius: 186, lat: -27.5969039, lng: -48.5494544 } }
108
+
109
+ it "the place shouldn't be within the radius" do
110
+ expect(Place.within_radius(test_data[:radius], test_data[:lat], test_data[:lng])).to be_empty
111
+ end
112
+
113
+ it { is_expected.to eq [@place] }
114
+ end
115
+
116
+ context "when query for place outside the box" do
117
+ let(:test_data) { { radius: 0.62, lat: -27.5969039, lng: -48.5494544 } }
118
+ it { is_expected.to be_empty }
119
+ end
120
+
121
+ context "when joining tables that are also geoloacted" do
122
+ let(:test_data) { { radius: 0.62, lat: -27.5969039, lng: -48.5494544 } }
123
+
124
+ subject { Place.within_box(test_data[:radius], test_data[:lat], test_data[:lng]) }
125
+
126
+ it "should work with objects having columns with the same name" do
127
+ expect do
128
+ Place
129
+ .joins(:events)
130
+ .within_radius(test_data[:radius], test_data[:lat], test_data[:lng]).to_a
131
+ end.to_not raise_error
132
+ end
133
+
134
+ it "should work with nested associations" do
135
+ expect do
136
+ Event
137
+ .joins(:events)
138
+ .within_radius(test_data[:radius], test_data[:lat], test_data[:lng]).to_a
139
+ end.to_not raise_error
140
+ end
141
+ end
142
+ end
143
+
76
144
  describe "#within_radius" do
77
145
  let(:test_data) { { lat: nil, lng: nil, radius: nil } }
78
146
  subject { Place.within_radius(test_data[:radius], test_data[:lat], test_data[:lng]) }
@@ -139,6 +207,75 @@ describe "ActiveRecord::Base.act_as_geolocated" do
139
207
  end
140
208
  end
141
209
 
210
+ describe "#within_radius with miles" do
211
+ let(:test_data) { { lat: nil, lng: nil, radius: nil } }
212
+ subject { Place.within_radius(test_data[:radius], test_data[:lat], test_data[:lng]) }
213
+ before(:all) do
214
+ # Place.distance_unit = :miles
215
+ Place.acts_as_geolocated distance_unit: :miles
216
+ @place = Place.create!(lat: -30.0277041, lng: -51.2287346)
217
+ end
218
+
219
+ after(:all) do
220
+ Place.acts_as_geolocated
221
+ @place.destroy
222
+ end
223
+
224
+ context "when query with null data" do
225
+ it { is_expected.to eq [] }
226
+ end
227
+
228
+ context "when query for the exact same point with radius 0" do
229
+ let(:test_data) { { lat: -30.0277041, lng: -51.2287346, radius: 0 } }
230
+ it { is_expected.to eq [@place] }
231
+ end
232
+
233
+ context "when query for place within radius" do
234
+ let(:test_data) { { radius: 2400, lat: -27.5969039, lng: -48.5494544 } }
235
+ it { is_expected.to eq [@place] }
236
+ end
237
+
238
+ context "when query for place outside the radius" do
239
+ let(:test_data) { { radius: 0.62, lat: -27.5969039, lng: -48.5494544 } }
240
+ it { is_expected.to eq [] }
241
+ end
242
+
243
+ context "uses lat and long of through table" do
244
+ subject do
245
+ Job.within_radius(test_data[:radius], test_data[:lat], test_data[:lng])
246
+ end
247
+
248
+ before(:all) do
249
+ @event = Event.create!(lat: -30.0277041, lng: -51.2287346)
250
+ @job = Job.create!(event: @event)
251
+ end
252
+
253
+ after(:all) do
254
+ @event.destroy
255
+ @job.destroy
256
+ end
257
+
258
+ context "when query with null data" do
259
+ it { is_expected.to eq [] }
260
+ end
261
+
262
+ context "when query for the exact same point with radius 0" do
263
+ let(:test_data) { { lat: -30.0277041, lng: -51.2287346, radius: 0 } }
264
+ it { is_expected.to eq [@job] }
265
+ end
266
+
267
+ context "when query for place within radius" do
268
+ let(:test_data) { { radius: 4_000_000, lat: -27.5969039, lng: -48.5494544 } }
269
+ it { is_expected.to eq [@job] }
270
+ end
271
+
272
+ context "when query for place outside the radius" do
273
+ let(:test_data) { { radius: 1000, lat: -27.5969039, lng: -48.5494544 } }
274
+ it { is_expected.to eq [] }
275
+ end
276
+ end
277
+ end
278
+
142
279
  describe "#order_by_distance" do
143
280
  let(:current_location) { { lat: nil, lng: nil, radius: nil } }
144
281
 
@@ -221,4 +358,46 @@ describe "ActiveRecord::Base.act_as_geolocated" do
221
358
  end
222
359
  end
223
360
  end
361
+
362
+ describe "#selecting_distance_from with miles" do
363
+ let(:current_location) { { lat: nil, lng: nil, radius: nil } }
364
+ subject do
365
+ Place
366
+ .order_by_distance(current_location[:lat], current_location[:lng])
367
+ .selecting_distance_from(current_location[:lat], current_location[:lng])
368
+ .first
369
+ .try { |p| [p.data, p.distance.to_f] }
370
+ end
371
+ before(:all) do
372
+ Place.acts_as_geolocated distance_unit: :miles
373
+ @place = Place.create!(data: "Amsterdam", lat: 52.370216, lng: 4.895168) # Amsterdam
374
+ end
375
+ after(:all) do
376
+ Place.acts_as_geolocated
377
+ @place.destroy
378
+ end
379
+ context "when selecting distance" do
380
+ let(:current_location) { { lat: 52.229676, lng: 21.012229 } } # Warsaw
381
+ it { is_expected.to eq ["Amsterdam", 680.410076641856] }
382
+ end
383
+
384
+ context "through table" do
385
+
386
+ subject { Job.all.selecting_distance_from(current_location[:lat], current_location[:lng]).first }
387
+
388
+ before(:all) do
389
+ @event = Event.create!(lat: -30.0277041, lng: -51.2287346)
390
+ @job = Job.create!(event: @event)
391
+ end
392
+
393
+ after(:all) do
394
+ @event.destroy
395
+ @job.destroy
396
+ end
397
+
398
+ context "when selecting distance" do
399
+ it { is_expected.to respond_to :distance }
400
+ end
401
+ end
402
+ end
224
403
  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.5.2
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Diogo Biazus
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-01 00:00:00.000000000 Z
11
+ date: 2021-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -143,7 +143,7 @@ homepage: http://github.com/diogob/activerecord-postgres-earthdistance
143
143
  licenses:
144
144
  - MIT
145
145
  metadata: {}
146
- post_install_message:
146
+ post_install_message:
147
147
  rdoc_options: []
148
148
  require_paths:
149
149
  - lib
@@ -158,14 +158,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
158
  - !ruby/object:Gem::Version
159
159
  version: 1.3.6
160
160
  requirements: []
161
- rubyforge_project:
162
- rubygems_version: 2.5.1
163
- signing_key:
161
+ rubygems_version: 3.1.4
162
+ signing_key:
164
163
  specification_version: 4
165
164
  summary: Check distances with latitude and longitude using PostgreSQL special indexes
166
- test_files:
167
- - spec/act_as_geolocated_spec.rb
168
- - spec/fixtures/event.rb
169
- - spec/fixtures/job.rb
170
- - spec/fixtures/place.rb
171
- - spec/spec_helper.rb
165
+ test_files: []