activerecord-postgres-postgis 0.1.0

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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +22 -0
  5. data/Gemfile +23 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +29 -0
  8. data/Rakefile +6 -0
  9. data/activerecord-postgres-postgis.gemspec +29 -0
  10. data/lib/activerecord-postgres-postgis.rb +10 -0
  11. data/lib/activerecord-postgres-postgis/active_record.rb +3 -0
  12. data/lib/activerecord-postgres-postgis/active_record/connection_adapters/column.rb +53 -0
  13. data/lib/activerecord-postgres-postgis/active_record/connection_adapters/oid.rb +33 -0
  14. data/lib/activerecord-postgres-postgis/active_record/connection_adapters/postgresql_adapter.rb +29 -0
  15. data/lib/activerecord-postgres-postgis/active_record/connection_adapters/quoting.rb +17 -0
  16. data/lib/activerecord-postgres-postgis/active_record/connection_adapters/schema_definitions.rb +49 -0
  17. data/lib/activerecord-postgres-postgis/active_record/connection_adapters/schema_statements.rb +42 -0
  18. data/lib/activerecord-postgres-postgis/arel/visitors/to_sql.rb +9 -0
  19. data/lib/activerecord-postgres-postgis/model.rb +35 -0
  20. data/lib/activerecord-postgres-postgis/railtie.rb +18 -0
  21. data/lib/activerecord-postgres-postgis/version.rb +7 -0
  22. data/lib/generators/postgis/setup_generator.rb +25 -0
  23. data/lib/tasks/postgis.rake +12 -0
  24. data/lib/templates/rails4/setup_postgis.rb +9 -0
  25. data/lib/templates/setup_postgis.rb +9 -0
  26. data/spec/dummy/rails-4.1.0/.gitignore +16 -0
  27. data/spec/dummy/rails-4.1.0/README.rdoc +28 -0
  28. data/spec/dummy/rails-4.1.0/Rakefile +6 -0
  29. data/spec/dummy/rails-4.1.0/app/assets/images/.keep +0 -0
  30. data/spec/dummy/rails-4.1.0/app/assets/javascripts/application.js +16 -0
  31. data/spec/dummy/rails-4.1.0/app/assets/stylesheets/application.css +15 -0
  32. data/spec/dummy/rails-4.1.0/app/controllers/application_controller.rb +5 -0
  33. data/spec/dummy/rails-4.1.0/app/controllers/concerns/.keep +0 -0
  34. data/spec/dummy/rails-4.1.0/app/helpers/application_helper.rb +2 -0
  35. data/spec/dummy/rails-4.1.0/app/mailers/.keep +0 -0
  36. data/spec/dummy/rails-4.1.0/app/models/.keep +0 -0
  37. data/spec/dummy/rails-4.1.0/app/models/concerns/.keep +0 -0
  38. data/spec/dummy/rails-4.1.0/app/models/foo.rb +5 -0
  39. data/spec/dummy/rails-4.1.0/app/views/layouts/application.html.erb +14 -0
  40. data/spec/dummy/rails-4.1.0/bin/bundle +3 -0
  41. data/spec/dummy/rails-4.1.0/bin/rails +8 -0
  42. data/spec/dummy/rails-4.1.0/bin/rake +8 -0
  43. data/spec/dummy/rails-4.1.0/bin/spring +18 -0
  44. data/spec/dummy/rails-4.1.0/config.ru +4 -0
  45. data/spec/dummy/rails-4.1.0/config/application.rb +32 -0
  46. data/spec/dummy/rails-4.1.0/config/boot.rb +4 -0
  47. data/spec/dummy/rails-4.1.0/config/database.yml +11 -0
  48. data/spec/dummy/rails-4.1.0/config/environment.rb +5 -0
  49. data/spec/dummy/rails-4.1.0/config/environments/development.rb +37 -0
  50. data/spec/dummy/rails-4.1.0/config/environments/production.rb +82 -0
  51. data/spec/dummy/rails-4.1.0/config/environments/test.rb +39 -0
  52. data/spec/dummy/rails-4.1.0/config/initializers/assets.rb +8 -0
  53. data/spec/dummy/rails-4.1.0/config/initializers/backtrace_silencers.rb +7 -0
  54. data/spec/dummy/rails-4.1.0/config/initializers/cookies_serializer.rb +3 -0
  55. data/spec/dummy/rails-4.1.0/config/initializers/filter_parameter_logging.rb +4 -0
  56. data/spec/dummy/rails-4.1.0/config/initializers/inflections.rb +16 -0
  57. data/spec/dummy/rails-4.1.0/config/initializers/mime_types.rb +4 -0
  58. data/spec/dummy/rails-4.1.0/config/initializers/session_store.rb +3 -0
  59. data/spec/dummy/rails-4.1.0/config/initializers/wrap_parameters.rb +14 -0
  60. data/spec/dummy/rails-4.1.0/config/locales/en.yml +23 -0
  61. data/spec/dummy/rails-4.1.0/config/routes.rb +56 -0
  62. data/spec/dummy/rails-4.1.0/config/secrets.yml +22 -0
  63. data/spec/dummy/rails-4.1.0/db/migrate/20140628210427_setup_postgis.rb +9 -0
  64. data/spec/dummy/rails-4.1.0/db/migrate/20140628230435_create_foos.rb +10 -0
  65. data/spec/dummy/rails-4.1.0/db/schema.rb +35 -0
  66. data/spec/dummy/rails-4.1.0/db/seeds.rb +7 -0
  67. data/spec/dummy/rails-4.1.0/lib/assets/.keep +0 -0
  68. data/spec/dummy/rails-4.1.0/lib/tasks/.keep +0 -0
  69. data/spec/dummy/rails-4.1.0/log/.keep +0 -0
  70. data/spec/dummy/rails-4.1.0/public/404.html +67 -0
  71. data/spec/dummy/rails-4.1.0/public/422.html +67 -0
  72. data/spec/dummy/rails-4.1.0/public/500.html +66 -0
  73. data/spec/dummy/rails-4.1.0/public/favicon.ico +0 -0
  74. data/spec/dummy/rails-4.1.0/public/robots.txt +5 -0
  75. data/spec/dummy/rails-4.1.0/vendor/assets/javascripts/.keep +0 -0
  76. data/spec/dummy/rails-4.1.0/vendor/assets/stylesheets/.keep +0 -0
  77. data/spec/migration_spec.rb +39 -0
  78. data/spec/model_spec.rb +16 -0
  79. data/spec/setup_generator_spec.rb +65 -0
  80. data/spec/spatial_spec.rb +51 -0
  81. data/spec/spec_helper.rb +114 -0
  82. data/spec/support/migration.rb +11 -0
  83. metadata +280 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f9aa50c6ce6da9571d94f676d2858022c24b7266
4
+ data.tar.gz: 1f6f2362576751d97bdcd4f363758126c6be436f
5
+ SHA512:
6
+ metadata.gz: cd380b3ac160df3eb0c03e2da64c22a0c79d833aaef7783810e84a4ca0b27a7a44476a999f9be5fbaf939567e6238bee9aa0ad6eb92fce8a5f832bb99c542784
7
+ data.tar.gz: cd73d7d4fb3c4ddc92ed4556c304c77ea475593ac454c85943835c2d1f46cb9e6376245dbd112df56066af4e921850362ba189b3baf535be6751ed82d67b80e7
@@ -0,0 +1,24 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .rbenv*
24
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,22 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
6
+ - ruby-head
7
+ - rbx-2
8
+ - rbx-head
9
+ addons:
10
+ postgresql: "9.3"
11
+ env:
12
+ - "RAILS_VERSION=4.1.0"
13
+ matrix:
14
+ allow_failures:
15
+ - env: "RAILS_VERSION=master"
16
+ - rvm: ruby-head
17
+ - rvm: rbx-head
18
+ script:
19
+ - cd spec/dummy/rails-$RAILS_VERSION; bundle exec rake db:migrate
20
+ - cd ../../../; bundle exec rake spec
21
+ before_script:
22
+ - psql -c 'create database activerecord_postgresql_postgis_test;' -U postgres
data/Gemfile ADDED
@@ -0,0 +1,23 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in activerecord-postgres-postgis.gemspec
4
+ gemspec
5
+
6
+ rails_version = ENV['RAILS_VERSION'] || 'default'
7
+
8
+ rails = case rails_version
9
+ when 'master'
10
+ { github: 'rails/rails' }
11
+ when 'default'
12
+ '>= 4.1.0'
13
+ else
14
+ "~> #{rails_version}"
15
+ end
16
+
17
+ gem 'rails', rails
18
+
19
+ gem 'coveralls', require: false
20
+
21
+ platforms :ruby do
22
+ gem 'pg'
23
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Anthony Smith
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.
@@ -0,0 +1,29 @@
1
+ # Activerecord::Postgres::Postgis
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'activerecord-postgres-postgis'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install activerecord-postgres-postgis
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( https://github.com/[my-github-username]/activerecord-postgres-postgis/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,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new :spec
5
+
6
+ task default: :spec
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'activerecord-postgres-postgis/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'activerecord-postgres-postgis'
8
+ spec.version = ActiveRecord::Postgres::Postgis::VERSION
9
+ spec.authors = ['Anthony Smith']
10
+ spec.email = ['anthony@sticksnleaves.com']
11
+ spec.summary = %q{Write a short summary. Required.}
12
+ spec.description = %q{Write a longer description. Optional.}
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'activerecord', '>= 3.2'
22
+ spec.add_dependency 'rake'
23
+ spec.add_dependency 'rgeo', '~> 0.3'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.6'
26
+ spec.add_development_dependency 'database_cleaner'
27
+ spec.add_development_dependency 'generator_spec'
28
+ spec.add_development_dependency 'rspec-rails'
29
+ end
@@ -0,0 +1,10 @@
1
+ require 'active_support'
2
+ require 'rgeo'
3
+
4
+ if defined?(Rails)
5
+ require 'activerecord-postgres-postgis/railtie'
6
+ else
7
+ ActiveSupport.on_load :active_record do
8
+ require File.expand_path('../lib/activerecord-postgres-postgis/active_record', __FILE__)
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ Dir["#{File.dirname(__FILE__)}/**/*.rb"].each { |f| require f }
2
+
3
+ ActiveRecord::Base.extend(ActiveRecord::Postgres::Postgis::Model)
@@ -0,0 +1,53 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class PostgreSQLColumn < Column
4
+ attr_reader :spatial_type, :srid
5
+
6
+ attr_accessor :oid_type
7
+
8
+ def initialize_with_spatial(name, default, oid_type, sql_type = nil, null = true)
9
+ initialize_without_spatial(name, default, oid_type, sql_type, null)
10
+
11
+ @spatial_type = extract_spatial_type(sql_type)
12
+ @srid = extract_srid(sql_type)
13
+
14
+ if spatial?
15
+ oid_type.srid = @srid
16
+ end
17
+ end
18
+
19
+ alias_method_chain :initialize, :spatial
20
+
21
+ def simplified_type_with_spatial(field_type)
22
+ if field_type =~ /^(?:geometry)/
23
+ :geometry
24
+ elsif field_type =~ /^(?:geography)/
25
+ :geography
26
+ else
27
+ simplified_type_without_spatial(field_type)
28
+ end
29
+ end
30
+
31
+ alias_method_chain :simplified_type, :spatial
32
+
33
+ def spatial?
34
+ !sql_type.match(/^(geometry|geography)/).nil?
35
+ end
36
+
37
+ private
38
+ def extract_spatial_type(sql_type)
39
+ if sql_type =~ /^(geometry|geography)\(([a-z]+)(,\d+)?\)/i
40
+ @limit = nil
41
+ "'#{$2.upcase}'"
42
+ end
43
+ end
44
+
45
+ def extract_srid(sql_type)
46
+ if sql_type =~ /^(geometry|geography)\(([a-z]+)(,(\d+))\)/i
47
+ @limit = nil
48
+ $4.to_i
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,33 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class PostgreSQLAdapter < AbstractAdapter
4
+ module OID
5
+ class Spatial < Type
6
+ attr_accessor :factory_generator, :srid
7
+
8
+ def initialize(factory_generator = nil)
9
+ @factory_generator = factory_generator
10
+ end
11
+
12
+ def type_cast(value)
13
+ if value.kind_of?(RGeo::Feature::Geometry)
14
+ RGeo::Feature.cast(value, @factory)
15
+ elsif value && value.respond_to?(:to_s)
16
+ marker = value[0, 1]
17
+ if marker == "\x00" || marker == "\x01" || value[0,4] =~ /[0-9a-fA-F]{4}/
18
+ RGeo::WKRep::WKBParser.new(@factory_generator, support_ewkb: true, default_srid: srid).parse(value)
19
+ else
20
+ RGeo::WKRep::WKTParser.new(@factory_generator, support_ewkt: true, default_srid: srid).parse(value)
21
+ end
22
+ else
23
+ nil
24
+ end
25
+ end
26
+ end
27
+
28
+ register_type('geometry', Spatial.new)
29
+ register_type('geography', Spatial.new(RGeo::Geographic.method(:spherical_factory)))
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class PostgreSQLAdapter < AbstractAdapter
4
+ def prepare_column_options_with_spatial(column, types)
5
+ spec = prepare_column_options_without_spatial(column, types)
6
+ spec[:spatial_type] = column.spatial_type if column.respond_to?(:spatial_type) && column.spatial_type
7
+ spec[:srid] = column.srid.to_s if column.respond_to?(:srid) && column.srid
8
+ spec
9
+ end
10
+
11
+ alias_method_chain :prepare_column_options, :spatial
12
+
13
+ def migration_keys_with_spatial
14
+ migration_keys_without_spatial + [:spatial_type, :srid]
15
+ end
16
+
17
+ alias_method_chain :migration_keys, :spatial
18
+
19
+ def native_database_types_with_spatial
20
+ native_database_types_without_spatial.merge({
21
+ geometry: { name: 'geometry' },
22
+ geography: { name: 'geography' }
23
+ })
24
+ end
25
+
26
+ alias_method_chain :native_database_types, :spatial
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class PostgreSQLAdapter < AbstractAdapter
4
+ module Quoting
5
+ def type_cast_with_spatial(value, column, array_member = false)
6
+ if value.kind_of?(RGeo::Feature::Geometry)
7
+ RGeo::WKRep::WKBGenerator.new(hex_format: true, type_format: :ewkb, emit_ewkb_srid: true).generate(value)
8
+ else
9
+ type_cast_without_spatial(value, column, array_member)
10
+ end
11
+ end
12
+
13
+ alias_method_chain :type_cast, :spatial
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,49 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ module ColumnMethods
4
+ # Adds geometry type for migrations. So you can add column to a table like:
5
+ # create_table :locations do |t|
6
+ # ...
7
+ # t.geometry :geom, srid: 423, type: 'LINESTRING'
8
+ # ...
9
+ # end
10
+ #
11
+ def geometry(name, options = {})
12
+ column(name, :geometry, options)
13
+ end
14
+
15
+ # Adds geography type for migrations. So you can add column to a table
16
+ # like:
17
+ # create_table :locations do |t|
18
+ # ...
19
+ # t.geography :geog, type: 'LINESTRING'
20
+ # ...
21
+ # end
22
+ #
23
+ def geography(name, options = {})
24
+ column(name, :geography, options)
25
+ end
26
+ end
27
+
28
+ class PostgreSQLAdapter::ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
29
+ attr_accessor :spatial_type, :srid
30
+ end
31
+
32
+ class PostgreSQLAdapter::TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
33
+ include ColumnMethods
34
+
35
+ def column_with_spatial(name, type = nil, options = {})
36
+ column = column_without_spatial(name, type, options)[name]
37
+ column.spatial_type = options[:spatial_type]
38
+ column.srid = options[:srid]
39
+ self
40
+ end
41
+
42
+ alias_method_chain :column, :spatial
43
+ end
44
+
45
+ class PostgreSQLAdapter::Table < ActiveRecord::ConnectionAdapters::Table
46
+ include ColumnMethods
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,42 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class PostgreSQLAdapter::SchemaCreation < ActiveRecord::ConnectionAdapters::AbstractAdapter::SchemaCreation
4
+ def add_column_options_with_spatial!(sql, options)
5
+ column = options.fetch(:column) { return super }
6
+ if column.type == :geometry
7
+ if column.spatial_type || column.srid
8
+ sql_params = column.spatial_type
9
+ sql_params << ',' if sql_params && column.srid
10
+ sql_params = column.srid.to_s.prepend(sql_params || '') if column.srid
11
+ sql << "(#{sql_params})" if sql_params
12
+ end
13
+ elsif column.type == :geography
14
+ if column.spatial_type || column.srid
15
+ sql_params = column.spatial_type
16
+ sql_params << ',' if sql_params
17
+ sql_params = 4326.to_s.prepend(sql_params || '')
18
+ sql << "(#{sql_params})" if sql_params
19
+ end
20
+ else
21
+ add_column_options_without_spatial!(sql, options)
22
+ end
23
+ end
24
+
25
+ alias_method_chain :add_column_options!, :spatial
26
+ end
27
+
28
+ module SchemaStatements
29
+ # Adds a spatial column to the table using the PostGIS
30
+ # "AddGeometryColumn()" function.
31
+ #
32
+ # This method exists for backwards compatability with PostGIS 1.x.
33
+ #
34
+ # Example:
35
+ # add_geometry_column :roads, :geom, srid: 423, spatial_type: 'LINESTRING', dimension: 2
36
+ #
37
+ def add_geometry_column(table_name, column_name, options = {})
38
+ execute "SELECT AddGeometryColumn('#{table_name}', '#{column_name}', #{options[:srid]}, '#{options[:spatial_type]}', #{options[:dimension]})"
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ module Arel
2
+ module Visitors
3
+ class ToSql < Arel::Visitors::Visitor
4
+ def visit_RGeo_Feature_Geometry(o, a)
5
+ quote(RGeo::WKRep::WKTGenerator.new(type_format: :ewkt, emit_ewkt_srid: true).generate(o))
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,35 @@
1
+ module ActiveRecord
2
+ module Postgres
3
+ module Postgis
4
+ FACTORY_GENERATORS = {
5
+ geometry: {
6
+ preferred: :preferred_factory,
7
+ simple: :simple_factory
8
+ },
9
+ geography: {
10
+ spherical: :spherical_factory,
11
+ simple_mercator: :simple_mercator_factory,
12
+ projected: :projected_factory
13
+ }
14
+ }
15
+
16
+ module Model
17
+ def spatial(column_name, factory, options = {})
18
+ column = columns_hash[column_name.to_s]
19
+ return unless column
20
+
21
+ column.oid_type.factory_generator = factory_generator_class(column.type).send(FACTORY_GENERATORS[column.type][factory], { srid: column.srid }.merge(options))
22
+ end
23
+
24
+ private
25
+ def factory_generator_class(column_type)
26
+ if column_type == :geometry
27
+ RGeo::Cartesian
28
+ elsif column_type == :geography
29
+ RGeo::Geographic
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end