mongoid_geospatial 1.0.0rc0

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 (109) hide show
  1. data/.document +5 -0
  2. data/.gitignore +49 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +11 -0
  5. data/README.md +330 -0
  6. data/Rakefile +18 -0
  7. data/lib/mongoid_geospatial/contexts/mongo.rb +115 -0
  8. data/lib/mongoid_geospatial/criteria.rb +5 -0
  9. data/lib/mongoid_geospatial/criterion/complex.rb +19 -0
  10. data/lib/mongoid_geospatial/criterion/inclusion.rb +14 -0
  11. data/lib/mongoid_geospatial/criterion/near_spatial.rb +50 -0
  12. data/lib/mongoid_geospatial/criterion/within_spatial.rb +60 -0
  13. data/lib/mongoid_geospatial/criterion.rb +3 -0
  14. data/lib/mongoid_geospatial/extensions/hash.rb +22 -0
  15. data/lib/mongoid_geospatial/extensions/symbol.rb +46 -0
  16. data/lib/mongoid_geospatial/field_option.rb +16 -0
  17. data/lib/mongoid_geospatial/fields/line_string.rb +18 -0
  18. data/lib/mongoid_geospatial/fields/point.rb +51 -0
  19. data/lib/mongoid_geospatial/fields/polygon.rb +22 -0
  20. data/lib/mongoid_geospatial/finders.rb +5 -0
  21. data/lib/mongoid_geospatial/geospatial/core_ext.rb +27 -0
  22. data/lib/mongoid_geospatial/geospatial/geo_near_results.rb +140 -0
  23. data/lib/mongoid_geospatial/geospatial.rb +86 -0
  24. data/lib/mongoid_geospatial/version.rb +5 -0
  25. data/lib/mongoid_geospatial.rb +16 -0
  26. data/mongoid_geospatial.gemspec +28 -0
  27. data/spec/config/mongod.conf +3 -0
  28. data/spec/config/mongoid.yml +18 -0
  29. data/spec/functional/contexts/mongo_spec.rb +127 -0
  30. data/spec/functional/criterion/inclusion_spec.rb +356 -0
  31. data/spec/functional/mongoid_geospatial_spec.rb +54 -0
  32. data/spec/functional/spatial/geo_near_results_spec.rb +78 -0
  33. data/spec/models/account.rb +19 -0
  34. data/spec/models/acolyte.rb +9 -0
  35. data/spec/models/address.rb +62 -0
  36. data/spec/models/address_component.rb +5 -0
  37. data/spec/models/agent.rb +10 -0
  38. data/spec/models/alert.rb +5 -0
  39. data/spec/models/animal.rb +21 -0
  40. data/spec/models/answer.rb +4 -0
  41. data/spec/models/bar.rb +9 -0
  42. data/spec/models/birthday.rb +13 -0
  43. data/spec/models/book.rb +5 -0
  44. data/spec/models/business.rb +7 -0
  45. data/spec/models/callbacks.rb +57 -0
  46. data/spec/models/category.rb +13 -0
  47. data/spec/models/circus.rb +7 -0
  48. data/spec/models/comment.rb +13 -0
  49. data/spec/models/country_code.rb +6 -0
  50. data/spec/models/description.rb +11 -0
  51. data/spec/models/division.rb +5 -0
  52. data/spec/models/drug.rb +5 -0
  53. data/spec/models/employer.rb +5 -0
  54. data/spec/models/entry.rb +6 -0
  55. data/spec/models/event.rb +20 -0
  56. data/spec/models/farm.rb +10 -0
  57. data/spec/models/favorite.rb +6 -0
  58. data/spec/models/fruits.rb +11 -0
  59. data/spec/models/game.rb +18 -0
  60. data/spec/models/ghost.rb +7 -0
  61. data/spec/models/house.rb +4 -0
  62. data/spec/models/inheritance.rb +90 -0
  63. data/spec/models/league.rb +5 -0
  64. data/spec/models/location.rb +5 -0
  65. data/spec/models/login.rb +6 -0
  66. data/spec/models/membership.rb +4 -0
  67. data/spec/models/mixed_drink.rb +4 -0
  68. data/spec/models/name.rb +13 -0
  69. data/spec/models/namespacing.rb +11 -0
  70. data/spec/models/observed.rb +41 -0
  71. data/spec/models/override.rb +16 -0
  72. data/spec/models/owner.rb +6 -0
  73. data/spec/models/page.rb +5 -0
  74. data/spec/models/page_question.rb +4 -0
  75. data/spec/models/paranoid_post.rb +18 -0
  76. data/spec/models/parents.rb +32 -0
  77. data/spec/models/patient.rb +15 -0
  78. data/spec/models/person.rb +146 -0
  79. data/spec/models/pet.rb +7 -0
  80. data/spec/models/pet_owner.rb +6 -0
  81. data/spec/models/phone.rb +7 -0
  82. data/spec/models/player.rb +23 -0
  83. data/spec/models/post.rb +26 -0
  84. data/spec/models/preference.rb +9 -0
  85. data/spec/models/question.rb +8 -0
  86. data/spec/models/quiz.rb +6 -0
  87. data/spec/models/rating.rb +8 -0
  88. data/spec/models/river.rb +20 -0
  89. data/spec/models/role.rb +5 -0
  90. data/spec/models/service.rb +6 -0
  91. data/spec/models/shelf.rb +5 -0
  92. data/spec/models/slave_address_numbers.rb +14 -0
  93. data/spec/models/survey.rb +5 -0
  94. data/spec/models/tag.rb +6 -0
  95. data/spec/models/tracking_id_validation_history.rb +25 -0
  96. data/spec/models/translation.rb +5 -0
  97. data/spec/models/tree.rb +9 -0
  98. data/spec/models/user.rb +9 -0
  99. data/spec/models/user_account.rb +10 -0
  100. data/spec/models/vet_visit.rb +5 -0
  101. data/spec/models/video.rb +9 -0
  102. data/spec/models/wiki_page.rb +6 -0
  103. data/spec/spec_helper.rb +51 -0
  104. data/spec/support/authentication.rb +29 -0
  105. data/spec/unit/criterion/complex_spec.rb +15 -0
  106. data/spec/unit/criterion/inclusion_spec.rb +0 -0
  107. data/spec/unit/criterion/near_spatial_spec.rb +39 -0
  108. data/spec/unit/criterion/within_spatial_spec.rb +52 -0
  109. metadata +339 -0
@@ -0,0 +1,6 @@
1
+ class PetOwner
2
+ include Mongoid::Document
3
+ field :title
4
+ embeds_one :pet
5
+ embeds_one :address, :as => :addressable
6
+ end
@@ -0,0 +1,7 @@
1
+ class Phone
2
+ include Mongoid::Document
3
+ field :number
4
+ key :number
5
+ embeds_one :country_code
6
+ embedded_in :person
7
+ end
@@ -0,0 +1,23 @@
1
+ class Player
2
+ include Mongoid::Document
3
+ field :active, :type => Boolean
4
+ field :frags, :type => Integer
5
+ field :deaths, :type => Integer
6
+ field :status
7
+
8
+ named_scope :active, criteria.where(:active => true) do
9
+ def extension
10
+ "extension"
11
+ end
12
+ end
13
+ named_scope :inactive, :where => { :active => false }
14
+ named_scope :frags_over, lambda { |count| { :where => { :frags.gt => count } } }
15
+ named_scope :deaths_under, lambda { |count| criteria.where(:deaths.lt => count) }
16
+ scope :deaths_over, lambda { |count| criteria.where(:deaths.gt => count) }
17
+
18
+ class << self
19
+ def alive
20
+ criteria.where(:status => "Alive")
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ class Post
2
+ include Mongoid::Document
3
+ include Mongoid::MultiParameterAttributes
4
+ include Mongoid::Versioning
5
+ include Mongoid::Timestamps
6
+
7
+ field :title, :type => String
8
+ field :content, :type => String
9
+ field :rating, :type => Integer
10
+
11
+ belongs_to :person
12
+ belongs_to :author, :foreign_key => :author_id, :class_name => "User"
13
+ has_and_belongs_to_many :tags
14
+ has_many :videos, :validate => false
15
+
16
+ scope :recent, where(:created_at => { "$lt" => Time.now, "$gt" => 30.days.ago })
17
+ scope :posting, where(:content.in => [ "Posting" ])
18
+
19
+ validates_format_of :title, :without => /\$\$\$/
20
+
21
+ class << self
22
+ def old
23
+ where(:created_at => { "$lt" => 30.days.ago })
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ class Preference
2
+ include Mongoid::Document
3
+ field :name, :type => String
4
+ field :value, :type => String
5
+ field :ranking, :type => Integer
6
+ has_and_belongs_to_many :people
7
+ validates_length_of :name, :minimum => 2, :allow_nil => true
8
+ scope :posting, where(:value.in => [ "Posting" ])
9
+ end
@@ -0,0 +1,8 @@
1
+ class Question
2
+ include Mongoid::Document
3
+ field :content
4
+ embedded_in :survey
5
+ embeds_many :answers
6
+
7
+ accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
8
+ end
@@ -0,0 +1,6 @@
1
+ class Quiz
2
+ include Mongoid::Document
3
+ include Mongoid::Timestamps::Created
4
+ field :topic
5
+ embeds_many :pages
6
+ end
@@ -0,0 +1,8 @@
1
+ class Rating
2
+ include Mongoid::Document
3
+ field :value, :type => Integer
4
+ referenced_in :ratable, :polymorphic => true
5
+ references_many :comments
6
+ validates_numericality_of :value, :less_than => 100, :allow_nil => true
7
+ validates :ratable, :associated => true
8
+ end
@@ -0,0 +1,20 @@
1
+ class River
2
+ include Mongoid::Document
3
+ include Mongoid::Geospatial
4
+
5
+ field :name, type: String
6
+ field :length, type: Integer
7
+ field :average_discharge, type: Integer
8
+ field :source, type: Array, spatial: true
9
+ # set return_array to true if you do not want a hash returned all the time
10
+ field :mouth, type: Array, spatial: {lat: 'latitude', lng: 'longitude'}
11
+ field :mouth_array, type: Array, spatial: {return_array: true}
12
+
13
+ # simplified spatial indexing
14
+ # you can only index one field in mongodb < 1.9
15
+ spatial_index :source
16
+ # alternatives
17
+ # index [[ :spatial, Mongo::GEO2D ]], {min:-400, max:400}
18
+ # index [[ :spatial, Mongo::GEO2D ]], {bit:32}
19
+ # index [[ :spatial, Mongo::GEO2D ],:name]
20
+ end
@@ -0,0 +1,5 @@
1
+ class Role
2
+ include Mongoid::Document
3
+ field :name, :type => String
4
+ recursively_embeds_many
5
+ end
@@ -0,0 +1,6 @@
1
+ class Service
2
+ include Mongoid::Document
3
+ field :sid
4
+ embedded_in :person
5
+ validates_numericality_of :sid
6
+ end
@@ -0,0 +1,5 @@
1
+ class Shelf
2
+ include Mongoid::Document
3
+ field :level, :type => Integer
4
+ recursively_embeds_one
5
+ end
@@ -0,0 +1,14 @@
1
+ # These models used for Github 263
2
+ class Slave
3
+ include Mongoid::Document
4
+ field :first_name
5
+ field :last_name
6
+ embeds_many :address_numbers
7
+ end
8
+
9
+ class AddressNumber
10
+ include Mongoid::Document
11
+ field :country_code, :type => Integer, :default => 1
12
+ field :number
13
+ embedded_in :slave
14
+ end
@@ -0,0 +1,5 @@
1
+ class Survey
2
+ include Mongoid::Document
3
+ embeds_many :questions
4
+ accepts_nested_attributes_for :questions, :reject_if => lambda{ |a| a[:content].blank? }, :allow_destroy => true
5
+ end
@@ -0,0 +1,6 @@
1
+ class Tag
2
+ include Mongoid::Document
3
+ field :text, :type => String
4
+ references_and_referenced_in_many :posts
5
+ references_and_referenced_in_many :related, :class_name => "Tag"
6
+ end
@@ -0,0 +1,25 @@
1
+ # These models are spcific to test for Github #313.
2
+ module MyCompany
3
+ module Model
4
+ class TrackingId
5
+ include Mongoid::Document
6
+ include Mongoid::Timestamps
7
+ store_in :tracking_ids
8
+ embeds_many :validation_history, :class_name => "MyCompany::Model::TrackingIdValidationHistory"
9
+ end
10
+ end
11
+ end
12
+
13
+ module MyCompany
14
+ module Model
15
+ # A TrackingId validation state change
16
+ class TrackingIdValidationHistory
17
+ include Mongoid::Document
18
+ field :old_state, :type => String
19
+ field :new_state, :type => String
20
+ field :when_changed, :type => DateTime
21
+ attr_protected :_id
22
+ embedded_in :tracking_id, :class_name => "MyCompany::Model::TrackingId"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ class Translation
2
+ include Mongoid::Document
3
+ field :language
4
+ embedded_in :name
5
+ end
@@ -0,0 +1,9 @@
1
+ class Tree
2
+ include Mongoid::Document
3
+
4
+ field :name
5
+ field :evergreen, :type => Boolean
6
+
7
+ scope :verdant, where(:evergreen => true)
8
+ default_scope asc(:name)
9
+ end
@@ -0,0 +1,9 @@
1
+ class User
2
+ include Mongoid::Document
3
+
4
+ field :name
5
+
6
+ references_one :account, :foreign_key => :creator_id
7
+ references_many :posts, :foreign_key => :author_id
8
+ references_many :descriptions
9
+ end
@@ -0,0 +1,10 @@
1
+ class UserAccount
2
+ include Mongoid::Document
3
+ field :username
4
+ field :name
5
+ field :email
6
+ validates_uniqueness_of :username, :message => "is not unique"
7
+ validates_uniqueness_of :email, :message => "is not unique", :case_sensitive => false
8
+ validates_length_of :name, :minimum => 2, :allow_nil => true
9
+ references_and_referenced_in_many :people
10
+ end
@@ -0,0 +1,5 @@
1
+ class VetVisit
2
+ include Mongoid::Document
3
+ field :date, :type => Date
4
+ embedded_in :pet
5
+ end
@@ -0,0 +1,9 @@
1
+ class Video
2
+ include Mongoid::Document
3
+ field :title
4
+ embedded_in :person
5
+ referenced_in :post
6
+ referenced_in :game
7
+
8
+ default_scope asc(:title)
9
+ end
@@ -0,0 +1,6 @@
1
+ class WikiPage
2
+ include Mongoid::Document
3
+ include Mongoid::Versioning
4
+ field :title, :type => String
5
+ max_versions 5
6
+ end
@@ -0,0 +1,51 @@
1
+ require 'pry'
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+
5
+ MODELS = File.join(File.dirname(__FILE__), "models")
6
+ SUPPORT = File.join(File.dirname(__FILE__), "support")
7
+ $LOAD_PATH.unshift(MODELS)
8
+ $LOAD_PATH.unshift(SUPPORT)
9
+
10
+ require "mongoid"
11
+ require "mocha"
12
+ require "rspec"
13
+ require "mongoid_geospatial"
14
+
15
+ LOGGER = Logger.new($stdout)
16
+
17
+ if RUBY_VERSION >= '1.9.2'
18
+ YAML::ENGINE.yamler = 'syck'
19
+ end
20
+
21
+ Mongoid.configure do |config|
22
+ name = "mongoid_geospatial_test"
23
+ config.master = Mongo::Connection.new.db(name)
24
+ config.logger = nil
25
+ config.allow_dynamic_fields = true
26
+ end
27
+
28
+ Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
29
+ Dir[ File.join(SUPPORT, "*.rb") ].each { |file| require File.basename(file) }
30
+
31
+ RSpec.configure do |config|
32
+ config.mock_with(:mocha)
33
+
34
+ config.after(:suite) { Mongoid.purge! }
35
+ config.after(:each) do
36
+ Mongoid.database.collections.each do |collection|
37
+ unless collection.name =~ /^system\./
38
+ collection.remove
39
+ end
40
+ end
41
+ end
42
+
43
+ # We filter out the specs that require authentication if the database has not
44
+ # had the mongoid user set up properly.
45
+ user_configured = Support::Authentication.configured?
46
+ warn(Support::Authentication.message) unless user_configured
47
+
48
+ config.filter_run_excluding(:config => lambda { |value|
49
+ return true if value == :user && !user_configured
50
+ })
51
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ module Support #:nodoc:
3
+ module Authentication
4
+ extend self
5
+
6
+ def configured?
7
+ begin
8
+ master_uri = "mongodb://mongoid:test@localhost:27017/mongoid_geospatial_test"
9
+ Mongo::Connection.from_uri(master_uri)
10
+ true
11
+ rescue Mongo::AuthenticationError => e
12
+ false
13
+ end
14
+ end
15
+
16
+ def message
17
+ %Q{
18
+ ---------------------------------------------------------------------
19
+ A user needs to be configured for authentication, otherwise some
20
+ configuration specs will not get run. You may set it up from the
21
+ mongo console:
22
+
23
+ $ use mongoid_geospatial_test;
24
+ $ db.addUser("mongoid", "test");
25
+ ---------------------------------------------------------------------
26
+ }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criterion::Complex do
4
+
5
+ let(:complex) { Mongoid::Criterion::Complex.new(:key => :field, :operator => "gt") }
6
+
7
+ let(:value) { 40 }
8
+
9
+ context "#to_mongo_query" do
10
+ it "should turn value into appropriate query" do
11
+ complex.to_mongo_query(value).should == {"$gt" => value}
12
+ end
13
+ end
14
+
15
+ end
File without changes
@@ -0,0 +1,39 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criterion::NearSpatial do
4
+
5
+ let(:within) do
6
+ {
7
+ :flat => Mongoid::Criterion::WithinSpatial.new(:key => :field, :operator => "near"),
8
+ :sphere => Mongoid::Criterion::WithinSpatial.new(:key => :field, :operator => "nearSphere"),
9
+ }
10
+ end
11
+ NEAR = {
12
+ :flat =>
13
+ {
14
+ 'Point' => [[1,2],5],
15
+ 'Hash Point' => {:point => [-73.98, 40.77], :max => 5},
16
+ 'Hash Point Unit' => {:point => [-73.98, 40.77], :max => 5, :unit => :km}
17
+ },
18
+ :sphere =>
19
+ {
20
+ 'Point' => [[1,2],5],
21
+ 'Hash Point' => {:point => [-73.98, 40.77], :max => 5},
22
+ 'Hash Point Unit' => {:point => [-73.98, 40.77], :max => 5, :unit => :km}
23
+ }
24
+ }
25
+
26
+ context "#to_mongo_query" do
27
+
28
+ NEAR.each do |shape, points|
29
+ points.each do |input_name,input|
30
+ it "#{shape} should generate a query with #{input_name}" do
31
+ within[shape].to_mongo_query(input).should be_a_kind_of(Hash)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criterion::WithinSpatial do
4
+
5
+ let(:within) do
6
+ {
7
+ :box => Mongoid::Criterion::WithinSpatial.new(:key => :field, :operator => "box"),
8
+ :polygon => Mongoid::Criterion::WithinSpatial.new(:key => :field, :operator => "polygon"),
9
+ :center => Mongoid::Criterion::WithinSpatial.new(:key => :field, :operator => "center"),
10
+ :center_sphere => Mongoid::Criterion::WithinSpatial.new(:key => :field, :operator => "box"),
11
+ }
12
+ end
13
+ WITHIN = {
14
+ :box =>
15
+ {
16
+ 'Array of Arrays' => [[10,20], [15,25]],
17
+ 'Array of Hashes' => [{ x: 10, y: 20 }, { x: 15, y: 25 }],
18
+ 'Hash of Hashes' => { a: { x: 10, y: 20 }, b: { x: 15, y: 25 }}
19
+ },
20
+ :polygon =>
21
+ {
22
+ 'Array of Arrays' => [[10,20], [15,25]],
23
+ 'Array of Hashes' => [{ x: 10, y: 20 }, { x: 15, y: 25 }],
24
+ 'Hash of Hashes' => { a: { x: 10, y: 20 }, b: { x: 15, y: 25 }}
25
+ },
26
+ :center =>
27
+ {
28
+ 'Point' => [[1,2],5],
29
+ 'Hash Point' => {:point => [-73.98, 40.77], :max => 5},
30
+ 'Hash Point Unit' => {:point => [-73.98, 40.77], :max => 5, :unit => :km}
31
+ },
32
+ :center_sphere =>
33
+ {
34
+ 'Point' => [[1,2],5],
35
+ 'Hash Point' => {:point => [-73.98, 40.77], :max => 5},
36
+ 'Hash Point Unit' => {:point => [-73.98, 40.77], :max => 5, :unit => :km}
37
+ }
38
+ }
39
+
40
+ context "#to_mongo_query" do
41
+
42
+ WITHIN.each do |shape, points|
43
+ points.each do |input_name,input|
44
+ it "#{shape} should generate a query with #{input_name}" do
45
+ within[shape].to_mongo_query(input).should be_a_kind_of(Hash)
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ end
52
+