geo_foo 0.0.1 → 0.0.3

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.3
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{geo_foo}
8
- s.version = "0.0.1"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["agnat", "hukl"]
12
- s.date = %q{2010-03-12}
12
+ s.date = %q{2010-03-16}
13
13
  s.description = %q{Geo makes it easy to interact with Postgis without hacking too deep into AR. It is in a very early stage and should be considered experimental at most}
14
14
  s.email = %q{contact@smyck.org}
15
15
  s.extra_rdoc_files = [
@@ -30,16 +30,18 @@ Gem::Specification.new do |s|
30
30
  "lib/geo_foo/numeric.rb",
31
31
  "lib/geo_foo/scope.rb",
32
32
  "test/helper.rb",
33
+ "test/models/location.rb",
33
34
  "test/test_geo_foo.rb",
34
35
  "test_database.yml"
35
36
  ]
36
37
  s.homepage = %q{http://github.com/hukl/geo_foo}
37
38
  s.rdoc_options = ["--charset=UTF-8"]
38
39
  s.require_paths = ["lib"]
39
- s.rubygems_version = %q{1.3.5}
40
+ s.rubygems_version = %q{1.3.6}
40
41
  s.summary = %q{An experimental and extensible Rails/Postgis library}
41
42
  s.test_files = [
42
43
  "test/helper.rb",
44
+ "test/models/location.rb",
43
45
  "test/test_geo_foo.rb"
44
46
  ]
45
47
 
@@ -1,3 +1,4 @@
1
+ require 'geo_foo/core'
1
2
  require 'geo_foo/scope'
2
3
  require 'geo_foo/active_record'
3
4
  require 'geo_foo/numeric'
@@ -2,6 +2,7 @@ module GeoFoo
2
2
  module ActiveRecord
3
3
  def self.included(base)
4
4
  base.extend ClassMethods
5
+ base.send(:include, InstanceMethods)
5
6
  end
6
7
  end
7
8
 
@@ -11,18 +12,38 @@ module GeoFoo
11
12
  def self.within_radius lat, lon, radius
12
13
  scoped(
13
14
  :conditions => [
14
- "ST_DWithin(#{GeoFoo::Core.as_point(lat,lon)}, "\
15
+ "ST_DWithin(#{GeoFoo.as_point(lat,lon)}, "\
15
16
  "point, #{bbox_size(lat, radius)}) AND ST_Distance_Sphere(" \
16
- "point, #{GeoFoo::Core.as_point(lat,lon)}) < #{radius}"
17
+ "point, #{GeoFoo.as_point(lat,lon)}) < #{radius}"
17
18
  ]
18
19
  )
19
20
  end
20
21
  end
21
22
  end
22
23
 
24
+ # return latitude, longitude for a given id
25
+ def find_coords_by_id id
26
+ result = connection.execute(
27
+ "SELECT ST_Y(point), ST_X(point) FROM #{table_name} WHERE id = #{id}")[0]
28
+ # Intentionally return (y,x) which corresponds to (lat,lon). See as_point().
29
+ [result["st_y"].to_f, result["st_x"].to_f]
30
+ end
31
+
23
32
  # XXX handle case where lat is (close to) +-90deg (poles)
24
33
  def bbox_size latitude, radius
25
- (radius.to_f / (GeoFoo::Core::EarthRadius * Math.cos(latitude.to_rad))).to_deg
34
+ (radius.to_f / (GeoFoo::EarthRadius * Math.cos(latitude.to_rad))).to_deg
35
+ end
36
+ end
37
+
38
+ module InstanceMethods
39
+
40
+ def point_to_coords
41
+ result = self.class.connection.execute(
42
+ "SELECT ST_Y(point), ST_X(point) FROM #{self.class.table_name} " \
43
+ "WHERE id = #{self.id}"
44
+ )[0]
45
+
46
+ { :latitude => result["st_y"].to_f, :longitude => result["st_x"].to_f }
26
47
  end
27
48
  end
28
49
  end
@@ -1,23 +1,18 @@
1
1
  module GeoFoo
2
2
 
3
- module Core
4
- SRID = 4326 # WGS-84
5
- EarthRadius = 6370986.0 # meters (as used by postgis' ST_Distance_Sphere())
6
- TableName = "locations"
7
-
8
- # execute an SQL query on the database
9
- def self.execute query
10
- ActiveRecord::Base.connection.execute( query ).to_a
11
- end
12
-
13
- # return a postgis string representation of the given coordinates
14
- def self.as_point lat, lon
15
- # Intentionally use (lat,lon) and not (lon,lat), because latitude is the
16
- # 'horizontal' coordinate.
17
- # See: http://archives.postgresql.org/pgsql-general/2008-02/msg01393.php
18
- "ST_GeomFromText('POINT(#{lon} #{lat})', #{SRID})"
19
- end
3
+ SRID = 4326 # WGS-84
4
+ EarthRadius = 6370986.0 # meters (as used by postgis' ST_Distance_Sphere())
5
+
6
+ # return a postgis string representation of the given coordinates
7
+ def self.as_point lat, lon
8
+ # Intentionally use (lat,lon) and not (lon,lat), because latitude is the
9
+ # 'horizontal' coordinate.
10
+ # See: http://archives.postgresql.org/pgsql-general/2008-02/msg01393.php
11
+ "ST_GeomFromText('POINT(#{lon} #{lat})', #{SRID})"
12
+ end
20
13
 
14
+ module Core
15
+
21
16
  # find all locations within a radius for a given location
22
17
  def self.find_neighbours_by_coords lat, lon, radius=100.0
23
18
  # compute an appropriate bounding box size for this latitude
@@ -29,31 +24,7 @@ module GeoFoo
29
24
  "AND #{distance} < #{radius} "\
30
25
  "ORDER BY #{distance}").map { |row| row["id"].to_i }
31
26
  end
32
-
33
- # return latitude, longitude for a given id
34
- def self.find_coords_by_id id
35
- r = (execute "SELECT ST_Y(point), ST_X(point) FROM #{TableName} "\
36
- "WHERE id = #{id}")[0]
37
- # Intentionally return (y,x) which corresponds to (lat,lon). See as_point().
38
- [r["st_y"].to_f, r["st_x"].to_f]
39
- end
40
-
41
- # store a point in the location table. returns the points id.
42
- def self.store_location lat, lon
43
- (execute "INSERT INTO #{TableName} (point) VALUES (#{as_point(lat,lon)})"\
44
- "RETURNING id").first["id"].to_i
45
- end
46
-
47
- # delete a location from the database
48
- def self.delete_location id
49
- execute "DELETE FROM #{TableName} WHERE id = #{id}"
50
- end
51
-
52
- # returns the number of locations currently in the database
53
- def self.location_count
54
- (execute "SELECT count(*) FROM #{TableName}").first["count"].to_i
55
- end
56
-
27
+
57
28
  # migration helper: create the database table
58
29
  def self.create_table
59
30
  execute "CREATE TABLE #{TableName} (id serial PRIMARY KEY)"
@@ -5,12 +5,11 @@ require 'active_support'
5
5
  require 'active_support/test_case'
6
6
 
7
7
  config_file = File.join(File.dirname(__FILE__), '..', 'test_database.yml')
8
- database_config = YAML.load_file config_file
9
- database_config[:adapter] = 'postgresql'
10
- ActiveRecord::Base.establish_connection database_config
8
+ ActiveRecord::Base.establish_connection( YAML.load_file config_file )
11
9
 
12
10
  $LOAD_PATH.unshift(File.dirname(__FILE__))
13
11
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
12
+
14
13
  require 'geo_foo'
15
14
 
16
15
  class ActiveSupport::TestCase
@@ -27,5 +26,8 @@ class ActiveSupport::TestCase
27
26
  query(sql).first.first
28
27
  end
29
28
 
29
+ def point_for lat, lon
30
+ execute("SELECT #{GeoFoo.as_point(lat, lon)}")[0]["st_geomfromtext"]
31
+ end
30
32
 
31
33
  end
@@ -0,0 +1,5 @@
1
+ class Location < ActiveRecord::Base
2
+
3
+ add_geo_foo
4
+
5
+ end
@@ -1,25 +1,82 @@
1
- require 'geo_foo/core'
2
1
  require 'helper'
2
+ require 'models/location'
3
3
 
4
4
  class TestGeoFoo < ActiveSupport::TestCase
5
-
6
- test "database connection" do
7
- # perform a query first to 'wake-up' the connection
8
- assert_equal(query_scalar("SELECT 5").to_i, 5)
9
- assert ActiveRecord::Base.connected?, "database connection esteblished"
5
+
6
+ def setup
7
+ query = [
8
+ "CREATE TABLE locations ( id serial PRIMARY KEY );",
9
+ "SELECT AddGeometryColumn('locations', 'point', 4326, 'POINT', 2);",
10
+ "CREATE INDEX locations_point_index ON locations USING GIST (point);"
11
+ ].join
12
+
13
+ ActiveRecord::Base.connection.execute(query)
10
14
  end
11
-
15
+
16
+ def teardown
17
+ query = [
18
+ "DROP TABLE locations;",
19
+ "DELETE FROM geometry_columns WHERE f_table_name = 'locations';"
20
+ ].join
21
+ ActiveRecord::Base.connection.execute(query)
22
+ end
23
+
12
24
  test "postgis database is present" do
13
- assert(query('SELECT count(*) FROM geometry_columns'))
25
+ assert(query('SELECT postgis_full_version()'), 'postgis functions present')
26
+ assert(query('SELECT count(*) FROM geometry_columns'), 'postgis tables present')
27
+ assert(query('SELECT count(*) FROM spatial_ref_sys'), 'postgis tables present')
14
28
  end
15
29
 
16
30
  test "as_point" do
17
31
  latitude = 5
18
32
  longitude = 42
19
- point = GeoFoo::Core.as_point latitude, longitude
33
+ point = GeoFoo.as_point latitude, longitude
20
34
  assert(query("SELECT #{point}"))
21
35
  assert_equal(query_scalar("SELECT ST_X(#{point})").to_i, 42)
22
36
  assert_equal(query_scalar("SELECT ST_Y(#{point})").to_i, 5)
23
37
  end
24
38
 
39
+ test "setup of Location model" do
40
+ assert_not_nil Location
41
+ end
42
+
43
+ test "creating a location" do
44
+ assert_not_nil Location.create :point => point_for( 53.0, 13.0 )
45
+ end
46
+
47
+ test "within_radius is defined" do
48
+ assert defined?(Location.within_radius), '#within_radius is not defined'
49
+ end
50
+
51
+ test "as_point is defined" do
52
+ assert defined?(GeoFoo.as_point), '#as_point is not defined'
53
+ end
54
+
55
+ test "find locations within radius" do
56
+ Location.create :point => point_for( 53.0000001, 13.0000001 )
57
+ Location.create :point => point_for( 53.0000002, 13.0000002 )
58
+
59
+ assert_equal 2, Location.within_radius(53.0000001, 13.0000001, 100.0).size
60
+ end
61
+
62
+ test "find no locations within radius" do
63
+ Location.create :point => point_for( 53.0000001, 13.0000001 )
64
+ Location.create :point => point_for( 53.0000002, 13.0000002 )
65
+
66
+ assert_equal 0, Location.within_radius(54.0, 14.0, 100.0).size
67
+ end
68
+
69
+ test "point to coords" do
70
+ location = Location.create :point => point_for( 53.1, 13.1 )
71
+
72
+ assert (53.09...53.11).include?( location.point_to_coords[:latitude] )
73
+ assert (13.09...13.11).include?( location.point_to_coords[:longitude] )
74
+ end
75
+
76
+ test "find_coords_by_id" do
77
+ Location.create :point => point_for( 53.1, 13.1 )
78
+ assert (53.09...53.11).include?( Location.find_coords_by_id(Location.last.id)[0])
79
+ assert (13.09...13.11).include?( Location.find_coords_by_id(Location.last.id)[1])
80
+ end
81
+
25
82
  end
@@ -1,3 +1,7 @@
1
1
  # always use adapter: postgresql
2
+ adapter: postgresql
3
+ encoding: unicode
2
4
  username: postgres
3
5
  database: geo_foo_test
6
+ template: template_postgis
7
+ min_messages: PANIC
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geo_foo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 3
9
+ version: 0.0.3
5
10
  platform: ruby
6
11
  authors:
7
12
  - agnat
@@ -10,7 +15,7 @@ autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
17
 
13
- date: 2010-03-12 00:00:00 +01:00
18
+ date: 2010-03-16 00:00:00 +01:00
14
19
  default_executable:
15
20
  dependencies: []
16
21
 
@@ -37,6 +42,7 @@ files:
37
42
  - lib/geo_foo/numeric.rb
38
43
  - lib/geo_foo/scope.rb
39
44
  - test/helper.rb
45
+ - test/models/location.rb
40
46
  - test/test_geo_foo.rb
41
47
  - test_database.yml
42
48
  has_rdoc: true
@@ -52,21 +58,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
52
58
  requirements:
53
59
  - - ">="
54
60
  - !ruby/object:Gem::Version
61
+ segments:
62
+ - 0
55
63
  version: "0"
56
- version:
57
64
  required_rubygems_version: !ruby/object:Gem::Requirement
58
65
  requirements:
59
66
  - - ">="
60
67
  - !ruby/object:Gem::Version
68
+ segments:
69
+ - 0
61
70
  version: "0"
62
- version:
63
71
  requirements: []
64
72
 
65
73
  rubyforge_project:
66
- rubygems_version: 1.3.5
74
+ rubygems_version: 1.3.6
67
75
  signing_key:
68
76
  specification_version: 3
69
77
  summary: An experimental and extensible Rails/Postgis library
70
78
  test_files:
71
79
  - test/helper.rb
80
+ - test/models/location.rb
72
81
  - test/test_geo_foo.rb