geo_foo 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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