activerecord-postgres-earthdistance 0.5.2 → 0.7.2

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 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: []