mongoid_geospatial 2.0.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/Gemfile +2 -1
  2. data/README.md +84 -60
  3. data/lib/mongoid_geospatial.rb +3 -7
  4. data/lib/mongoid_geospatial/{geospatial → extensions}/core_ext.rb +0 -0
  5. data/lib/mongoid_geospatial/field_option.rb +3 -4
  6. data/lib/mongoid_geospatial/fields/geometry_field.rb +34 -0
  7. data/lib/mongoid_geospatial/fields/line_string.rb +5 -7
  8. data/lib/mongoid_geospatial/fields/point.rb +18 -33
  9. data/lib/mongoid_geospatial/fields/polygon.rb +6 -14
  10. data/lib/mongoid_geospatial/geospatial.rb +20 -25
  11. data/lib/mongoid_geospatial/version.rb +1 -1
  12. data/lib/mongoid_geospatial/wrappers/georuby.rb +28 -0
  13. data/lib/mongoid_geospatial/wrappers/rgeo.rb +32 -0
  14. data/spec/models/farm.rb +5 -2
  15. data/spec/models/person.rb +4 -14
  16. data/spec/models/phone.rb +1 -3
  17. data/spec/mongoid_geospatial/extensions/core_ext_spec.rb +20 -0
  18. data/spec/mongoid_geospatial/field_option_spec.rb +11 -0
  19. data/spec/mongoid_geospatial/fields/line_string_spec.rb +40 -0
  20. data/spec/mongoid_geospatial/fields/point_spec.rb +136 -10
  21. data/spec/mongoid_geospatial/fields/polygon_spec.rb +75 -0
  22. data/spec/mongoid_geospatial/geospatial_spec.rb +88 -3
  23. data/spec/mongoid_geospatial/wrappers/rgeo_spec.rb +43 -0
  24. data/spec/spec_helper.rb +5 -21
  25. metadata +14 -26
  26. data/lib/mongoid_geospatial/contextual/mongo.rb +0 -118
  27. data/lib/mongoid_geospatial/criteria.rb +0 -10
  28. data/lib/mongoid_geospatial/criterion/complex.rb +0 -26
  29. data/lib/mongoid_geospatial/criterion/inclusion.rb +0 -14
  30. data/lib/mongoid_geospatial/criterion/near_spatial.rb +0 -52
  31. data/lib/mongoid_geospatial/criterion/within_spatial.rb +0 -62
  32. data/lib/mongoid_geospatial/extensions/symbol.rb +0 -46
  33. data/lib/mongoid_geospatial/finders.rb +0 -5
  34. data/lib/mongoid_geospatial/geospatial/geo_near_results.rb +0 -140
  35. data/spec/mongoid_geospatial/contextual/mongo_spec.rb +0 -135
  36. data/spec/mongoid_geospatial/criterion/complex_spec.rb +0 -15
  37. data/spec/mongoid_geospatial/criterion/inclusion_spec.rb +0 -375
  38. data/spec/mongoid_geospatial/criterion/near_spatial_spec.rb +0 -39
  39. data/spec/mongoid_geospatial/criterion/within_spatial_spec.rb +0 -54
  40. data/spec/mongoid_geospatial/geospatial/geo_near_results_spec.rb +0 -78
  41. data/spec/mongoid_geospatial/mongoid_geospatial_spec.rb +0 -83
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module Geospatial
3
- VERSION = "2.0.0"
3
+ VERSION = "2.2.0"
4
4
  end
5
5
  end
@@ -0,0 +1,28 @@
1
+ require 'georuby'
2
+ # require 'mongoid_geospatial/extensions/georuby'
3
+
4
+ module Mongoid
5
+ module Geospatial
6
+
7
+ class Point
8
+ def to_geo
9
+ GeoRuby::SimpleFeatures::Point.from_x_y(x, y)
10
+ end
11
+ end
12
+
13
+
14
+ class LineString < Array
15
+ def to_geo
16
+ GeoRuby::SimpleFeatures::LineString.from_array(self)
17
+ end
18
+
19
+ end
20
+
21
+ class Polygon < GeometryField
22
+ def to_geo
23
+ GeoRuby::SimpleFeatures::Polygon.from_array(self)
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ require 'rgeo'
2
+ require 'mongoid_geospatial/extensions/rgeo_spherical_point_impl'
3
+
4
+ module Mongoid
5
+ module Geospatial
6
+
7
+ class Point
8
+ def to_geo
9
+ RGeo::Geographic.spherical_factory.point x, y
10
+ end
11
+ end
12
+
13
+
14
+ class LineString < GeometryField
15
+ def to_geo
16
+ RGeo::Geographic.spherical_factory.line_string self
17
+ end
18
+
19
+ end
20
+
21
+ class Polygon < GeometryField
22
+ def to_geo
23
+ points = self.map do |pair|
24
+ RGeo::Geographic.spherical_factory.point *pair
25
+ end
26
+ ring = RGeo::Geographic.spherical_factory.linear_ring points
27
+ RGeo::Geographic.spherical_factory.polygon ring
28
+ end
29
+
30
+ end
31
+ end
32
+ end
data/spec/models/farm.rb CHANGED
@@ -2,8 +2,11 @@ class Farm
2
2
  include Mongoid::Document
3
3
  include Mongoid::Geospatial
4
4
 
5
- field :name, type: String
6
- field :area, type: Polygon, spatial: true
5
+ field :name, type: String
6
+ field :geom, type: Point, spatial: true
7
+ field :area, type: Polygon, spatial: true
8
+ field :m2, type: Fixnum
7
9
 
10
+ spatial_index :geom
8
11
  spatial_index :area
9
12
  end
@@ -3,6 +3,7 @@ class Person
3
3
  include Mongoid::MultiParameterAttributes
4
4
  include Mongoid::Timestamps
5
5
  include Mongoid::Versioning
6
+ include Mongoid::Geospatial
6
7
 
7
8
  attr_accessor :mode
8
9
 
@@ -27,6 +28,9 @@ class Person
27
28
  field :reading, :type => Object
28
29
  field :bson_id, :type => bson_object_id_class
29
30
 
31
+ # Geo
32
+ field :location, :type => Point
33
+
30
34
  index age: 1
31
35
  index addresses: 1
32
36
  index dob: 1
@@ -49,21 +53,7 @@ class Person
49
53
  end
50
54
  end
51
55
 
52
- # embeds_many :services
53
-
54
-
55
- # has_many \
56
- # :posts,
57
- # :dependent => :delete,
58
- # :order => :rating.desc do
59
- # def extension
60
- # "Testing"
61
- # end
62
- # end
63
-
64
56
  accepts_nested_attributes_for :addresses
65
- accepts_nested_attributes_for :name, :update_only => true
66
-
67
57
 
68
58
  scope :minor, where(:age.lt => 18)
69
59
  scope :without_ssn, without(:ssn)
data/spec/models/phone.rb CHANGED
@@ -1,9 +1,7 @@
1
1
  class Phone
2
2
  include Mongoid::Document
3
3
  field :number
4
- if Mongoid::VERSION < '3'
5
- key :number
6
- end
4
+
7
5
  embeds_one :country_code
8
6
  embedded_in :person
9
7
  end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe "Core Extensions" do
4
+
5
+ describe Array do
6
+
7
+ it "should have a #to_xy method" do
8
+ [1,2,3].to_xy.should eql([1.0, 2.0])
9
+ end
10
+
11
+ end
12
+
13
+ describe Hash do
14
+
15
+ it "should have a #to_xy method" do
16
+ { x: 1.1, y: 2.1 }.to_xy.should eql([1.1, 2.1])
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Fields do
4
+
5
+ context "spatial" do
6
+ end
7
+
8
+ context "geom" do
9
+ end
10
+
11
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Geospatial::LineString do
4
+
5
+ describe "(de)mongoize" do
6
+
7
+ it "should support a field mapped as linestring" do
8
+ river = River.new(source: [[5,5],[6,5],[6,6],[5,6]])
9
+ river.source.should be_a Mongoid::Geospatial::LineString
10
+ river.source.should eq([[5,5],[6,5],[6,6],[5,6]])
11
+ end
12
+
13
+ it "should support a field mapped as linestring" do
14
+ River.create!(source: [[5,5],[6,5],[6,6],[5,6]])
15
+ River.first.source.should eq([[5,5],[6,5],[6,6],[5,6]])
16
+ end
17
+
18
+ it "should have a bounding box" do
19
+ geom = Mongoid::Geospatial::LineString.new [[1,5],[6,5],[6,6],[5,6]]
20
+ geom.bbox.should eq([[1,5], [6,6]])
21
+ end
22
+
23
+ it "should have a center point" do
24
+ geom = Mongoid::Geospatial::LineString.new [[1,1],[1,1],[9,9],[9,9]]
25
+ geom.center.should eq([5.5,5.5])
26
+ end
27
+
28
+ it "should have a radius helper" do
29
+ geom = Mongoid::Geospatial::LineString.new [[1,1],[1,1],[9,9],[9,9]]
30
+ geom.radius(10).should eq([[5.5,5.5], 10])
31
+ end
32
+
33
+ it "should have a radius sphere" do
34
+ geom = Mongoid::Geospatial::LineString.new [[1,1],[1,1],[9,9],[9,9]]
35
+ geom.radius_sphere(10)[1].should be_within(0.001).of(0.001569)
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -2,30 +2,156 @@ require "spec_helper"
2
2
 
3
3
  describe Mongoid::Geospatial::Point do
4
4
 
5
- describe "in use" do
5
+ it "should not inferfer with mongoid" do
6
+ Bar.create!(name: "Moe's")
7
+ Bar.count.should eql(1)
8
+ end
9
+
10
+ describe "queryable" do
11
+
12
+ before do
13
+ Bar.create_indexes
14
+ end
15
+
16
+ describe ":near :near_sphere" do
17
+
18
+ let!(:berlin) do
19
+ Bar.create(:name => :berlin, :location => [ 52.30, 13.25 ])
20
+ end
21
+
22
+ let!(:prague) do
23
+ Bar.create(:name => :prague, :location => [ 50.5, 14.26 ])
24
+ end
25
+
26
+ let!(:paris) do
27
+ Bar.create(:name => :paris, :location => [ 48.48, 2.20 ])
28
+ end
29
+
30
+ let!(:jim) do
31
+ Person.new(:location => [ 41.23, 2.9 ])
32
+ end
33
+
34
+ it "returns the documents sorted closest to furthest" do
35
+ Bar.where(:location.near => jim.location).should == [ paris, prague, berlin ]
36
+ end
37
+
38
+ it "returns the documents sorted closest to furthest sphere" do
39
+ person = Person.new(:location => [ 41.23, 2.9 ])
40
+ Bar.where(:location.near_sphere => jim.location).should == [ paris, prague, berlin ]
41
+ end
42
+
43
+ it "returns the documents sorted closest to furthest with max" do
44
+ Bar.near(location: jim.location).max_distance(location: 10).to_a.should == [ paris ] #, prague, berlin ]
45
+ end
46
+
47
+ end
48
+
49
+ describe ":within_circle :within_spherical_circle" do
50
+ let!(:mile1) do
51
+ Bar.create(:name => 'mile1', :location => [-73.997345, 40.759382])
52
+ end
53
+
54
+ let!(:mile3) do
55
+ Bar.create(:name => 'mile3', :location => [-73.927088, 40.752151])
56
+ end
57
+
58
+ let!(:mile7) do
59
+ Bar.create(:name => 'mile7', :location => [-74.0954913, 40.7161472])
60
+ end
61
+
62
+ let!(:mile9) do
63
+ Bar.create(:name => 'mile9', :location => [-74.0604951, 40.9178011])
64
+ end
65
+
66
+ let!(:elvis) do
67
+ Person.new(:location => [-73.98, 40.75])
68
+ end
69
+
70
+ it "returns the documents within a center_circle" do
71
+ Bar.where(:location.within_circle => [elvis.location, 250.0/Mongoid::Geospatial::EARTH_RADIUS_KM]).to_a.should == [ mile1 ]
72
+ end
73
+
74
+ it "returns the documents within a center_circle" do
75
+ Bar.where(:location.within_circle => [elvis.location, 500.0/Mongoid::Geospatial::EARTH_RADIUS_KM]).to_a.should include(mile3)
76
+ end
77
+
78
+ it "returns the documents within a center_sphere" do
79
+ Bar.where(:location.within_spherical_circle => [elvis.location, 0.0005]).to_a.should == [ mile1 ]
80
+ end
81
+
82
+ it "returns the documents within a center_sphere" do
83
+ Bar.where(:location.within_spherical_circle => [elvis.location, 0.5]).to_a.should include(mile9)
84
+ end
85
+ end
86
+
87
+ end
88
+
89
+ describe "(de)mongoize" do
6
90
 
7
91
  it "should mongoize array" do
8
92
  bar = Bar.new(location: [10, -9])
9
- bar.location.class.should eql(RGeo::Geographic::SphericalPointImpl)
93
+ bar.location.class.should eql(Mongoid::Geospatial::Point)
10
94
  bar.location.x.should be_within(0.1).of(10)
11
95
  bar.location.y.should be_within(0.1).of(-9)
12
96
  end
13
97
 
14
98
  it "should mongoize hash" do
15
- bar = Bar.new(location: {x: 10, y: -9})
16
- bar.location.class.should eql(RGeo::Geographic::SphericalPointImpl)
17
- bar.location.x.should be_within(0.1).of(10)
18
- bar.location.y.should be_within(0.1).of(-9)
99
+ geom = Bar.new(location: {x: 10, y: -9}).location
100
+ geom.class.should eql(Mongoid::Geospatial::Point)
101
+ geom.x.should be_within(0.1).of(10)
102
+ geom.y.should be_within(0.1).of(-9)
19
103
  end
20
104
 
21
- describe "instantiated" do
22
105
 
23
- let(:bar) { Bar.create!(name: 'Vitinho', location: [10,10]) }
106
+ describe "methods" do
107
+
108
+ it "should have a .to_a" do
109
+ bar = Bar.create!(location: [3,2])
110
+ bar.location.to_a[0..1].should == [3.0, 2.0]
111
+ end
24
112
 
25
- it "should demongoize to rgeo" do
26
- bar.location.class.should eql(RGeo::Geographic::SphericalPointImpl)
113
+ it "should have an array [] accessor" do
114
+ bar = Bar.create!(location: [3,2])
115
+ bar.location[0].should == 3.0
27
116
  end
28
117
 
118
+ it "should have an ActiveModel symbol accessor" do
119
+ bar = Bar.create!(location: [3,2])
120
+ bar[:location].should == [3,2]
121
+ end
122
+
123
+ it "should calculate distance between points" do
124
+ pending
125
+ bar = Bar.create!(location: [5,5])
126
+ bar2 = Bar.create!(location: [15,15])
127
+ bar.location.distance(bar2.location).should be_within(1).of(1561283.8)
128
+ end
129
+
130
+ it "should calculate 3d distances by default" do
131
+ pending
132
+ bar = Bar.create! location: [-73.77694444, 40.63861111 ]
133
+ bar2 = Bar.create! location: [-118.40, 33.94] #,:unit=>:mi, :spherical => true)
134
+ bar.location.distance(bar2.location).to_i.should be_within(1).of(2469)
135
+ end
136
+
137
+ end
138
+
139
+ # should raise
140
+ # geom.to_geo
141
+
142
+ describe "with rgeo" do
143
+
144
+ describe "instantiated" do
145
+
146
+ let(:bar) { Bar.create!(name: 'Vitinho', location: [10,10]) }
147
+
148
+ it "should demongoize to rgeo" do
149
+ bar.location.class.should eql(Mongoid::Geospatial::Point)
150
+ end
151
+
152
+ end
153
+
154
+
29
155
  end
30
156
 
31
157
  end
@@ -2,5 +2,80 @@ require "spec_helper"
2
2
 
3
3
  describe Mongoid::Geospatial::Polygon do
4
4
 
5
+ describe "(de)mongoize" do
6
+
7
+ it "should support a field mapped as polygon" do
8
+ farm = Farm.new(area: [[5,5],[6,5],[6,6],[5,6]])
9
+ farm.area.should eq([[5,5],[6,5],[6,6],[5,6]])
10
+ farm.area.should be_a Mongoid::Geospatial::Polygon
11
+ end
12
+
13
+ it "should store as array on mongo" do
14
+ Farm.create(area: [[5,5],[6,5],[6,6],[5,6]])
15
+ Farm.first.area.should eq([[5,5],[6,5],[6,6],[5,6]])
16
+ end
17
+
18
+ it "should have a bounding box" do
19
+ geom = Mongoid::Geospatial::Polygon.new [[1,5],[6,5],[6,6],[5,6]]
20
+ geom.bbox.should eq([[1,5], [6,6]])
21
+ end
22
+
23
+ it "should have a center point" do
24
+ geom = Mongoid::Geospatial::Polygon.new [[1,1],[1,1],[9,9],[9,9]]
25
+ geom.center.should eq([5.5,5.5])
26
+ end
27
+
28
+ it "should have a radius helper" do
29
+ geom = Mongoid::Geospatial::Polygon.new [[1,1],[1,1],[9,9],[9,9]]
30
+ geom.radius(10).should eq([[5.5,5.5], 10])
31
+ end
32
+
33
+ it "should have a radius sphere" do
34
+ geom = Mongoid::Geospatial::Polygon.new [[1,1],[1,1],[9,9],[9,9]]
35
+ geom.radius_sphere(10)[1].should be_within(0.001).of(0.001569)
36
+ end
37
+
38
+
39
+ describe "with rgeo" do
40
+ # farm.area.should be_a RGeo::Geographic::SphericalPolygonImpl
41
+ end
42
+
43
+ end
44
+
45
+ describe "query" do
46
+
47
+ context ":box, :polygon" do
48
+
49
+ before do
50
+ Farm.create_indexes
51
+ end
52
+
53
+ let!(:ranch) do
54
+ Farm.create(:name => 'Ranch', area: [[1, 1],[3, 3]], :geom => [2, 2])
55
+ end
56
+
57
+ let!(:farm) do
58
+ Farm.create(name: 'Farm', area: [[47, 1],[49, 1.5],[49, 3],[46, 5]], geom: [47.5, 2.26])
59
+ end
60
+
61
+ it "returns the documents within a box" do
62
+ Farm.where(:geom.within_box => ranch.area ).to_a.should == [ ranch ]
63
+ end
64
+
65
+ it "returns the documents within a polygon" do
66
+ Farm.where(:geom.within_polygon => farm.area).to_a.should == [ farm ]
67
+ end
68
+
69
+ it "returns the documents within a center" do
70
+ Farm.where(:geom.within_circle => [ranch.geom, 0.4]).first.should eq(ranch)
71
+ end
72
+
73
+ it "returns the documents within a center_sphere" do
74
+ Farm.where(:geom.within_spherical_circle => [ranch.geom, 0.1]).first.should eq(ranch)
75
+ end
76
+
77
+ end
78
+
79
+ end
5
80
 
6
81
  end