Permalink
Browse files

enable integration with geocoder for mongo using reverse internal arr…

…ay format [lng,lat]
  • Loading branch information...
1 parent 2df768b commit dd9c8de98634577dc0fde9da9ff8d1e053934db1 @kristianmandrup committed Sep 7, 2012
View
@@ -91,7 +91,14 @@ GEM
treetop (~> 1.4.8)
method_source (0.7.1)
mime-types (1.18)
+ mongoid (3.0.5)
+ activemodel (~> 3.1)
+ moped (~> 1.1)
+ origin (~> 1.0)
+ tzinfo (~> 0.3.22)
+ moped (1.2.1)
multi_json (1.2.0)
+ origin (1.0.7)
polyglot (0.3.3)
pry (0.9.8.4)
coderay (~> 1.0.5)
@@ -172,6 +179,7 @@ DEPENDENCIES
guard-spork
jasmine
jquery-rails
+ mongoid (~> 3)
pry
rails (~> 3.2.1)
rspec-rails
View
@@ -74,6 +74,12 @@ Mongoid example:
field :location, :type => Array
+By default this uses the [lng, lat] position format. You can reverse this format, by specifying `:pos_order => [:lng, :lat]`
+
+From [geocoder](https://github.com/alexreisner/geocoder) - Latitude/Longitude Order.
+
+_"Coordinates are generally printed and spoken as latitude, then longitude ([lat,lon]).Geocoder respects this convention and always expects method arguments to be given in [lat,lon] order. However, MongoDB requires that coordinates be stored in [lon,lat] order as per the GeoJSON spec (geojson.org/geojson-spec.html#positions), so internally they are stored “backwards.” However, this does not affect order of arguments to methods when using Mongoid or MongoMapper."_
+
== How to?
=== QuickStart!
In your controller:
@@ -33,7 +33,8 @@ def acts_as_gmappable args = {}
# purposefully no default.
# Leaving out the :position arg means we are using the default lat/lng to store coordinates
- :position => args[:position],
+ :position => args[:position],
+ :pos_order => args[:pos_order] || [:lat, :lng],
:msg => args[:msg] || "Address invalid",
:validation => args[:validation].nil? ? true : args[:validation],
@@ -26,7 +26,7 @@ module Gmaps4rails
#
class JsonBuilder
- delegate :position, :lat_column, :lng_column, :to => :@options
+ delegate :position, :lat_column, :lng_column, :pos_order, :to => :@options
def initialize(object)
@object, @json_hash, @custom_json = object, Hash.new, nil
@@ -127,12 +127,20 @@ def position_from_array?
position #if gmaps4rails_options[:position] is filled, means user is indicating an array
end
+ def lat_index
+ pos_order.first == :lat ? 0 : 1
+ end
+
+ def lng_index
+ pos_order.first == :lng ? 0 : 1
+ end
+
def lat
- position_from_array? ? @object.send("#{position}")[0] : @object.send("#{lat_column}")
+ position_from_array? ? @object.send("#{position}")[lat_index] : @object.send("#{lat_column}")
end
def lng
- position_from_array? ? @object.send("#{position}")[1] : @object.send("#{lng_column}")
+ position_from_array? ? @object.send("#{position}")[lng_index] : @object.send("#{lng_column}")
end
end
@@ -4,7 +4,7 @@ class ModelHandler
attr_accessor :options, :object
- delegate :process_geocoding, :check_process, :checker, :lat_column, :lng_column, :position, :msg, :validation,
+ delegate :process_geocoding, :check_process, :checker, :lat_column, :lng_column, :position, :pos_order, :msg, :validation,
:language, :protocol, :address, :callback, :normalized_address,
:to => :options
@@ -31,7 +31,11 @@ def retrieve_coordinates
# sets array for non relationnal db
def set_position
- object.send("#{position}=", [lat, lng])
+ if pos_order.first == :lat
+ object.send("#{position}=", [lat, lng])
+ else
+ object.send("#{position}=", [lng, lat])
+ end
end
#sets regular columns
@@ -0,0 +1,18 @@
+if RUBY_VERSION == "1.9.3"
+
+ require 'mongoid'
+
+ class GeoPlace
+ include Mongoid::Document
+ include Gmaps4rails::ActsAsGmappable
+
+ # Array position format in the form: [lng, lat]
+ # This format is f.ex used by *geocoder* gem
+ acts_as_gmappable :address => :address, :position => :pos, :pos_order => [:lng, :lat]
+
+ field :pos, :type => Array
+ field :address, :type => String
+ field :gmaps, :type => Boolean
+ end
+
+end
@@ -0,0 +1,16 @@
+FactoryGirl.define do
+ factory :geo_place do
+
+ trait :paris do
+ address "Paris, France"
+ end
+
+ trait :invalid do
+ address "home"
+ end
+
+ address "Toulon, France"
+
+ factory :geo_place_paris, :traits => [:paris]
+ end
+end
@@ -0,0 +1,37 @@
+if RUBY_VERSION == "1.9.3"
+
+ require 'spec_helper'
+
+ include Geocoding
+
+ set_gmaps4rails_options!
+
+ # Mongoid 3.x only
+ require 'mongoid'
+ require 'moped'
+
+ Mongoid.configure do |config|
+ config.connect_to('mongoid_geo_test')
+ end
+
+ describe Gmaps4rails::ActsAsGmappable do
+
+ # Tests Array position format in the form: [lng, lat]
+ # F.ex required for integration with *geocoder* gem
+ let(:geo_place) { Factory(:geo_place) }
+ let(:invalid_geo_place) { Factory.build(:invalid_geo_place) }
+
+ before(:each) do
+ Geocoding.stub_geocoding
+ end
+
+ context "standard configuration, valid place" do
+ it "should save longitude and latitude to the customized position array" do
+ set_gmaps4rails_options!(:position => 'location', :pos_order => [:lng, :lat])
+ geo_place.pos.should_not be_nil
+ geo_place.should have_same_position_as TOULON
+ end
+ end
+ end
+
+end
@@ -30,7 +30,7 @@ def has_same_content_as?(actual, expected)
class PositionMatcher
attr_reader :object, :position_hash
- delegate :position, :lat_column, :lng_column, :to => :@options
+ delegate :position, :lat_column, :lng_column, :pos_order, :to => :@options
def initialize object, position_hash
@object, @position_hash = object, position_hash
@@ -43,12 +43,20 @@ def same_pos?
protected
+ def lat_index
+ pos_order.first == :lat ? 0 : 1
+ end
+
+ def lng_index
+ pos_order.first == :lng ? 0 : 1
+ end
+
def lat
- position ? object.send("#{position}")[0] : object.send("#{lat_column}")
+ position ? object.send("#{position}")[lat_index] : object.send("#{lat_column}")
end
def lng
- position ? object.send("#{position}")[1] : object.send("#{lng_column}")
+ position ? object.send("#{position}")[lng_index] : object.send("#{lng_column}")
end
end

0 comments on commit dd9c8de

Please sign in to comment.