geo_foo 0.0.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.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ THE BEER-WARE LICENSE Copyright (c) 2010 hukl, agnat
2
+
3
+ As long as you retain this notice you can do whatever you want with this stuff.
4
+ If we meet some day, and you think this stuff is worth it, you can buy us a beer
5
+ in return.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
8
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
9
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
10
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
11
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
12
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
13
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,29 @@
1
+ = geo_foo
2
+
3
+ Run
4
+
5
+ rake build
6
+ rake install
7
+
8
+ = Running the tests
9
+ To run the tests you need a postgresql server with postgis extensions installed.
10
+
11
+ * create an empty database +geo_foo_test+ from your postgis template
12
+ * set your settings in <tt>test_database.yml</tt>.
13
+
14
+ Now run:
15
+ rake [test]
16
+
17
+ == Note on Patches/Pull Requests
18
+
19
+ * Fork the project.
20
+ * Make your feature addition or bug fix.
21
+ * Add tests for it. This is important so I don't break it in a
22
+ future version unintentionally.
23
+ * Commit, do not mess with rakefile, version, or history.
24
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
25
+ * Send me a pull request. Bonus points for topic branches.
26
+
27
+ == Copyright
28
+
29
+ Copyright (c) 2010 hukl, agnat. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "geo_foo"
9
+ gem.summary = %Q{An experimental and extensible Rails/Postgis library}
10
+ gem.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}
11
+ gem.email = "contact@smyck.org"
12
+ gem.homepage = "http://github.com/hukl/geo_foo"
13
+ gem.authors = ["agnat", "hukl"]
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "geo_foo #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/geo_foo.gemspec ADDED
@@ -0,0 +1,56 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{geo_foo}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["agnat", "hukl"]
12
+ s.date = %q{2010-03-12}
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
+ s.email = %q{contact@smyck.org}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "geo_foo.gemspec",
27
+ "lib/geo_foo.rb",
28
+ "lib/geo_foo/active_record.rb",
29
+ "lib/geo_foo/core.rb",
30
+ "lib/geo_foo/numeric.rb",
31
+ "lib/geo_foo/scope.rb",
32
+ "test/helper.rb",
33
+ "test/test_geo_foo.rb",
34
+ "test_database.yml"
35
+ ]
36
+ s.homepage = %q{http://github.com/hukl/geo_foo}
37
+ s.rdoc_options = ["--charset=UTF-8"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = %q{1.3.5}
40
+ s.summary = %q{An experimental and extensible Rails/Postgis library}
41
+ s.test_files = [
42
+ "test/helper.rb",
43
+ "test/test_geo_foo.rb"
44
+ ]
45
+
46
+ if s.respond_to? :specification_version then
47
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
48
+ s.specification_version = 3
49
+
50
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
51
+ else
52
+ end
53
+ else
54
+ end
55
+ end
56
+
@@ -0,0 +1,29 @@
1
+ module GeoFoo
2
+ module ActiveRecord
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+ end
7
+
8
+ module ClassMethods
9
+ def add_geo_foo
10
+ self.class_eval do
11
+ def self.within_radius lat, lon, radius
12
+ scoped(
13
+ :conditions => [
14
+ "ST_DWithin(#{GeoFoo::Core.as_point(lat,lon)}, "\
15
+ "point, #{bbox_size(lat, radius)}) AND ST_Distance_Sphere(" \
16
+ "point, #{GeoFoo::Core.as_point(lat,lon)}) < #{radius}"
17
+ ]
18
+ )
19
+ end
20
+ end
21
+ end
22
+
23
+ # XXX handle case where lat is (close to) +-90deg (poles)
24
+ def bbox_size latitude, radius
25
+ (radius.to_f / (GeoFoo::Core::EarthRadius * Math.cos(latitude.to_rad))).to_deg
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,70 @@
1
+ module GeoFoo
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
20
+
21
+ # find all locations within a radius for a given location
22
+ def self.find_neighbours_by_coords lat, lon, radius=100.0
23
+ # compute an appropriate bounding box size for this latitude
24
+ # XXX handle case where lat is (close to) +-90deg (poles)
25
+ bbox_size= (radius.to_f / (EarthRadius * Math.cos(lat.to_rad))).to_deg
26
+ distance = "ST_Distance_Sphere(point, #{as_point(lat,lon)})"
27
+ (execute "SELECT (id) FROM #{TableName} "\
28
+ "WHERE ST_DWithin(#{as_point(lat,lon)}, point, #{bbox_size}) "\
29
+ "AND #{distance} < #{radius} "\
30
+ "ORDER BY #{distance}").map { |row| row["id"].to_i }
31
+ 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
+
57
+ # migration helper: create the database table
58
+ def self.create_table
59
+ execute "CREATE TABLE #{TableName} (id serial PRIMARY KEY)"
60
+ execute "SELECT AddGeometryColumn('#{TableName}', 'point', #{SRID}, 'POINT', 2)"
61
+ execute "CREATE INDEX #{TableName}_point_index ON #{TableName} USING GIST (point)"
62
+ end
63
+
64
+ # migration helper: drop the database table
65
+ def self.drop_table
66
+ execute "DROP TABLE #{TableName}"
67
+ end
68
+ end
69
+
70
+ end
@@ -0,0 +1,8 @@
1
+ class Numeric
2
+ def to_rad
3
+ self * (Math::PI / 180)
4
+ end
5
+ def to_deg
6
+ self * (180 / Math::PI)
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module GeoFoo
2
+ module Scope
3
+
4
+ def self.hello
5
+ puts "hello"
6
+ end
7
+
8
+ end
9
+ end
data/lib/geo_foo.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'geo_foo/scope'
2
+ require 'geo_foo/active_record'
3
+ require 'geo_foo/numeric'
4
+
5
+ module GeoFoo
6
+
7
+ end
8
+
9
+ begin
10
+ ActiveRecord::Base.class_eval do
11
+ include GeoFoo::ActiveRecord
12
+ end
13
+ rescue
14
+ true
15
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'active_record'
4
+ require 'active_support'
5
+ require 'active_support/test_case'
6
+
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
11
+
12
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ require 'geo_foo'
15
+
16
+ class ActiveSupport::TestCase
17
+
18
+ def execute sql
19
+ ActiveRecord::Base.connection.execute sql
20
+ end
21
+
22
+ def query sql
23
+ ActiveRecord::Base.connection.query sql
24
+ end
25
+
26
+ def query_scalar sql
27
+ query(sql).first.first
28
+ end
29
+
30
+
31
+ end
@@ -0,0 +1,25 @@
1
+ require 'geo_foo/core'
2
+ require 'helper'
3
+
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"
10
+ end
11
+
12
+ test "postgis database is present" do
13
+ assert(query('SELECT count(*) FROM geometry_columns'))
14
+ end
15
+
16
+ test "as_point" do
17
+ latitude = 5
18
+ longitude = 42
19
+ point = GeoFoo::Core.as_point latitude, longitude
20
+ assert(query("SELECT #{point}"))
21
+ assert_equal(query_scalar("SELECT ST_X(#{point})").to_i, 42)
22
+ assert_equal(query_scalar("SELECT ST_Y(#{point})").to_i, 5)
23
+ end
24
+
25
+ end
data/test_database.yml ADDED
@@ -0,0 +1,3 @@
1
+ # always use adapter: postgresql
2
+ username: postgres
3
+ database: geo_foo_test
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geo_foo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - agnat
8
+ - hukl
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2010-03-12 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: 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
18
+ email: contact@smyck.org
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - LICENSE
25
+ - README.rdoc
26
+ files:
27
+ - .document
28
+ - .gitignore
29
+ - LICENSE
30
+ - README.rdoc
31
+ - Rakefile
32
+ - VERSION
33
+ - geo_foo.gemspec
34
+ - lib/geo_foo.rb
35
+ - lib/geo_foo/active_record.rb
36
+ - lib/geo_foo/core.rb
37
+ - lib/geo_foo/numeric.rb
38
+ - lib/geo_foo/scope.rb
39
+ - test/helper.rb
40
+ - test/test_geo_foo.rb
41
+ - test_database.yml
42
+ has_rdoc: true
43
+ homepage: http://github.com/hukl/geo_foo
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --charset=UTF-8
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.3.5
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: An experimental and extensible Rails/Postgis library
70
+ test_files:
71
+ - test/helper.rb
72
+ - test/test_geo_foo.rb