nobrainer_geospatial 1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a41dfb97afec3cc5eb575023b632cae745ac8617
4
+ data.tar.gz: 3ee068c97f4b579dc25a5f0630e68c1cdf90c33e
5
+ SHA512:
6
+ metadata.gz: 9ec644dccb5c2d641cfc4dba206e30a8e77351d1dd15a0bbddf1d24ff39e2d6427e2057aab91bcfa57955b89fcf63a5020eea3bfcd59a69441a72eb621c5c05a
7
+ data.tar.gz: 1968ad7d0b8db40c4199c339bb84857d7ece50ea97bbab574b7e83d31b8d4d773a125dd44f8bac2e94e49b078cff7d229d70bf4ade1c85305b2829ebb13b3965
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Joshua Harding
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # NobrainerGeospatial
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'nobrainer_geospatial'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install nobrainer_geospatial
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( https://github.com/[my-github-username]/nobrainer_geospatial/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create a new Pull Request
@@ -0,0 +1,124 @@
1
+ require 'nobrainer_geospatial/version'
2
+ require 'nobrainer_geospatial/types/geo_point'
3
+ require 'nobrainer_geospatial/types/geo_polygon'
4
+
5
+ module NoBrainer
6
+ class GeoResultSet
7
+ attr_accessor :rql, :klass
8
+
9
+ def initialize(klass, rql)
10
+ self.rql = rql
11
+ self.klass = klass
12
+ end
13
+
14
+ def to_a
15
+ NoBrainer.run { self.rql }.to_a.map {|r| new_from_db(r) }
16
+ end
17
+
18
+ def all
19
+ to_a
20
+ end
21
+
22
+ def first
23
+ new_from_db NoBrainer.run { self.rql }.first
24
+ end
25
+
26
+ def each(&block)
27
+ NoBrainer.run { self.rql }.each do |result|
28
+ block.call(new_from_db result)
29
+ end
30
+ end
31
+
32
+ def count
33
+ NoBrainer.run { self.rql.count }
34
+ end
35
+
36
+ def where(args = nil, &block)
37
+ if block_given?
38
+ GeoResultSet.new(self.klass, self.rql.filter(block))
39
+ else
40
+ GeoResultSet.new(self.klass, self.rql.filter(args))
41
+ end
42
+ end
43
+
44
+ def limit(n)
45
+ GeoResultSet.new(self.klass, self.rql.limit(n))
46
+ end
47
+
48
+ def skip(n)
49
+ GeoResultSet.new(self.klass, self.rql.skip(n))
50
+ end
51
+
52
+ def order_by(args, order = :asc)
53
+
54
+ conditions = []
55
+
56
+ raise "Invalid sort order: #{order}" unless order == :asc || order == :desc
57
+
58
+ if args.class == Array
59
+ conditions = args.map do |arg|
60
+ if order == :asc
61
+ RethinkDB::RQL.new.asc(arg)
62
+ else
63
+ RethinkDB::RQL.new.desc(arg)
64
+ end
65
+ end
66
+ else
67
+ if order == :asc
68
+ conditions = RethinkDB::RQL.new.asc(args)
69
+ else
70
+ conditions = RethinkDB::RQL.new.desc(args)
71
+ end
72
+ end
73
+
74
+ GeoResultSet.new(self.klass, self.rql.order_by(*conditions))
75
+ end
76
+
77
+ def [](index)
78
+ to_a()[index]
79
+ end
80
+
81
+ def to_rql
82
+ self.rql
83
+ end
84
+
85
+ private
86
+ def new_from_db(result)
87
+ obj = klass.new_from_db(result)
88
+ if result['_distance']
89
+ obj.singleton_class.class_eval do
90
+ attr_accessor :distance
91
+ end
92
+ obj.distance = result['_distance']
93
+ end
94
+ return obj
95
+ end
96
+ end
97
+ end
98
+
99
+ module NoBrainer
100
+ module GeoQueries
101
+
102
+ def self.included base
103
+ base.extend ClassMethods
104
+ end
105
+
106
+ module ClassMethods
107
+ def nearest(point, options)
108
+ # if we get an array convert to RQL
109
+ if point.class == Array
110
+ point = RethinkDB::RQL.new.point(*point)
111
+ end
112
+ NoBrainer::GeoResultSet.new(self, self.rql_table.get_nearest(point, options).map {|result| result['doc'].merge({'_distance' => result['dist']})})
113
+ end
114
+
115
+ def intersecting(polygon, options)
116
+ if polygon.class == Array
117
+ polygon = RethinkDB::RQL.new.polygon(*polygon)
118
+ end
119
+ NoBrainer::GeoResultSet.new(self, self.rql_table.get_intersecting(polygon, options))
120
+ end
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,36 @@
1
+ module NoBrainer::GeoSpatial
2
+ class Point < Struct.new(:longitude, :latitude)
3
+
4
+ def to_rql
5
+ RethinkDB::RQL.new.point(self.longitude, self.latitude)
6
+ end
7
+
8
+ class << self
9
+ def nobrainer_cast_user_to_model(value)
10
+ case value
11
+ when NoBrainer::GeoSpatial::Point then value
12
+ when Array then
13
+ new(value[0], value[1])
14
+ when Hash then
15
+ longitude = value[:longitude] ||= value[:long] ||= value['longitude'] ||= value['long']
16
+ latitude = value[:latitude] ||= value[:lat] ||= value['latitude'] ||= value['latitude']
17
+ raise NoBrainer::Error::InvalidType.new('longitude out of range') if longitude < -180 || longitude > 180
18
+ raise NoBrainer::Error::InvalidType.new('latitude out of range') if latitude < -90 || latitude > 90
19
+ raise 'You must supply :longitude and :latitude!' unless latitude && longitude
20
+ new(longitude, latitude)
21
+ else raise NoBrainer::Error::InvalidType
22
+ end
23
+ end
24
+
25
+ def nobrainer_cast_model_to_db(value)
26
+ RethinkDB::RQL.new.point(value.longitude, value.latitude)
27
+ end
28
+
29
+ # This class method translates a value from the database to the proper type.
30
+ # It is used when reading from the database.
31
+ def nobrainer_cast_db_to_model(value)
32
+ NoBrainer::GeoSpatial::Point.new(value['coordinates'][0], value['coordinates'][1])
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,71 @@
1
+ module NoBrainer::GeoSpatial
2
+ class Polygon
3
+
4
+ attr_accessor :coordinates
5
+
6
+ def initialize(values)
7
+ # OK, values is either going to be a pair of coords like:
8
+ # [ [lon1, lat1], [lon2, lat2] ], ...
9
+ # OR
10
+ # [point1, point2], ...
11
+ # so we should have either all numeric or an array of arrays...
12
+ raise NoBrainer::Error::InvalidType.new('You must supply at least 4 coordinates') if values.length < 4
13
+
14
+ # check to make sure we're not getting invalid parameters or mixed parameters...
15
+ unless values.all? {|c| c.is_a? Numeric} || values.all? {|c| c.is_a? Array}
16
+ raise NoBrainer::Error::InvalidType.new('Points must be an Array or list of numeric')
17
+ end
18
+
19
+ self.coordinates = []
20
+
21
+ # convert from list of coords to a paired list...
22
+ if values.all? {|c| c.is_a? Numeric}
23
+ raise NoBrainer::Error::InvalidType.new('Must have even number of coordinates!') if values.length.odd?
24
+ values.each_slice(2) do |coords|
25
+ self.coordinates << [coords[0], coords[1]]
26
+ end
27
+ else
28
+ # we already had a paired list... just assign it straight across...
29
+ self.coordinates = values
30
+ end
31
+
32
+ check_coordinates(self.coordinates)
33
+
34
+ end
35
+
36
+ private
37
+ def check_coordinates(points)
38
+ points.each do |point|
39
+ longitude = point[0]
40
+ latitude = point[1]
41
+ if longitude < -180 || longitude > 180
42
+ raise NoBrainer::Error::InvalidType.new('Longitude is out of bounds')
43
+ end
44
+ if latitude < -90 || latitude > 90
45
+ raise NoBrainer::Error::InvalidType.new('Latitude is out of bounds')
46
+ end
47
+ end
48
+ end
49
+
50
+ class << self
51
+ def nobrainer_cast_user_to_model(value)
52
+ case value
53
+ when NoBrainer::GeoSpatial::Polygon then value
54
+ when Array then
55
+ new(value)
56
+ else raise NoBrainer::Error::InvalidType
57
+ end
58
+ end
59
+
60
+ def nobrainer_cast_model_to_db(value)
61
+ RethinkDB::RQL.new.polygon(*value.coordinates)
62
+ end
63
+
64
+ # This class method translates a value from the database to the proper type.
65
+ # It is used when reading from the database.
66
+ def nobrainer_cast_db_to_model(value)
67
+ NoBrainer::GeoSpatial::Polygon.new(*value['coordinates'])
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,5 @@
1
+ module NoBrainer
2
+ module Geospatial
3
+ VERSION = '1.1'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nobrainer_geospatial
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.1'
5
+ platform: ruby
6
+ authors:
7
+ - Joshua Harding
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ requirement: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: '1.6'
25
+ prerelease: false
26
+ type: :development
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ prerelease: false
40
+ type: :development
41
+ - !ruby/object:Gem::Dependency
42
+ name: nobrainer
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ prerelease: false
54
+ type: :runtime
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ prerelease: false
68
+ type: :development
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ prerelease: false
82
+ type: :development
83
+ description: Geospatial support for NoBrainer
84
+ email:
85
+ - josh@statewidesoftware.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - lib/nobrainer_geospatial.rb
91
+ - lib/nobrainer_geospatial/version.rb
92
+ - lib/nobrainer_geospatial/types/geo_polygon.rb
93
+ - lib/nobrainer_geospatial/types/geo_point.rb
94
+ - LICENSE.txt
95
+ - README.md
96
+ homepage: ''
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 2.1.9
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Geospatial support for NoBrainer.
120
+ test_files: []