enable integration with geocoder for mongo using reverse internal array format [lng,lat] #263

Closed
wants to merge 6 commits into
from
+310 −44
Split
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:
@@ -1,20 +0,0 @@
-<% content_for :scripts do %>
-<%= javascript_include_tag *js_dependencies %>
-
-<script type="text/javascript">
-<%=raw options.to_gmaps4rails %>
-</script>
-<% end %>
-
-<% case dom.map_provider %>
-<% when "mapquest" %>
-<div id="<%= dom.map_id %>" style="width:750px; height:475px;">
- <!-- TODO: change this style dynamically -->
-</div>
-<% when "bing" %>
- <div id="<%= dom.map_id %>" class="<%= dom.map_class %>"></div>
-<% else %>
-<div class="<%= dom.container_class %>">
- <div id="<%= dom.map_id %>" class="<%= dom.map_class %>"></div>
-</div>
-<% end %>
@@ -0,0 +1,3 @@
+<% content_for :scripts do %>
+ <%= javascript_include_tag *js_dependencies %>
+<% end %>
@@ -0,0 +1,2 @@
+- content_for :scripts do
+ = javascript_include_tag *js_dependencies
@@ -5,6 +5,8 @@ class InstallGenerator < Rails::Generators::Base
desc 'Creates a Gmaps4rails initializer and copies the assets to the public folder.'
+ class_option :views, :type => :string, :default => nil, :desc => 'copy partials to app/views of Rails app'
+
def copy_locale
if Rails::VERSION::MINOR >= 1
copy_file "#{source_assets_base_path}gmaps4rails.base.js.coffee", "#{destination_assets_base_path}gmaps4rails.base.js.coffee"
@@ -23,6 +25,30 @@ def copy_locale
copy_file "../../../public/stylesheets/gmaps4rails.css", "public/stylesheets/gmaps4rails.css"
end
end
+
+ def copy_views
+ return unless valid_template_type?
+ copy_file File.join(source_views_path, "_gmaps4rails_libs.html.#{template_type}"), File.join(destination_views_path, "_gmaps4rails_lib.html.#{template_type}")
+ end
+
+ protected
+
+ def template_type
+ options[:views].to_s.to_sym
+ end
+
+ def valid_template_type?
+ [:erb, :haml].include? template_type
+ end
+
+ def source_views_path
+ '../../../app/views/gmaps4rails'
+ end
+
+ def destination_views_path
+ 'app/views/gmaps4rails'
+ end
+
def source_assets_base_path
'../../../app/assets/javascripts/gmaps4rails/'
View
@@ -3,7 +3,6 @@ module Gmaps4rails
require 'gmaps4rails/base'
class Engine < Rails::Engine
-
initializer "gmaps4rails view helpers" do |app|
ActionView::Base.send :include, Gmaps4railsHelper
end
@@ -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],
@@ -8,6 +8,7 @@ module Gmaps4rails
require 'gmaps4rails/extensions/enumerable'
require 'gmaps4rails/extensions/hash'
+ autoload :Config, 'gmaps4rails/config'
autoload :ModelHandler, 'gmaps4rails/model_handler'
autoload :ActsAsGmappable, 'gmaps4rails/acts_as_gmappable'
@@ -0,0 +1,47 @@
+require 'singleton'
+
+module Gmaps4rails
+ def self.config
+ Config.instance
+ end
+
+ class Config
+ include Singleton
+
+ def options
+ yaml_loader.load
+ end
+
+ protected
+
+ def yaml_loader
+ @yaml_loader ||= YamlLoader.new
+ end
+
+ class YamlLoader
+ attr_writer :config_file, :config_path
+
+ def load
+ @load ||= HashWithIndifferentAccess.new load_yaml
+ end
+
+ def config_path
+ Rails.root.join 'config', config_file
+ end
+
+ def config_file
+ @config_file ||= 'gmaps4rails.yml'
+ end
+
+ protected
+
+ def load_yaml
+ @yaml ||= begin
+ YAML.load File.read(config_path)
+ rescue
+ {}
+ end
+ end
+ end
+ end
+end
@@ -12,22 +12,62 @@ def gmaps4rails(builder)
# full helper to pass all variables and their options
# @params [Hash] options is a Hash containing data and options. Example: { markers:{ data: @json, options: { do_clustering: true } } }
- def gmaps(options)
+ def gmaps(options = {})
+ options = Gmaps4rails.config.options.merge(options)
+
+ gmaps_libs(options) if options[:with_libs]
+
+ options_with_indifferent_access = options.with_indifferent_access
+ view_helper = Gmaps4rails::ViewHelper.new(options_with_indifferent_access)
+ gmaps4rails_map view_helper.dom_attributes, options_with_indifferent_access
+ end
+
+ def gmaps_libs(options = {})
+ options_with_indifferent_access = options.with_indifferent_access
+ view_helper = Gmaps4rails::ViewHelper.new(options_with_indifferent_access)
+
+ js_dependencies = Gmaps4rails.escape_js_url ? view_helper.js_dependencies_array : view_helper.js_dependencies_array.map(&:html_safe)
+
+ content_for :scripts do
+ javascript_include_tag(*js_dependencies)
+ end
+
+ # render partial: '/gmaps4rails/gmaps4rails_libs',
+ # :locals => {
+ # :js_dependencies => js_dependencies,
+ # :options => options_with_indifferent_access
+ # }
+ end
+
+ def gmaps_libs_now(options = {})
options_with_indifferent_access = options.with_indifferent_access
view_helper = Gmaps4rails::ViewHelper.new(options_with_indifferent_access)
- js_dependencies = if Gmaps4rails.escape_js_url
- view_helper.js_dependencies_array
- else
- view_helper.js_dependencies_array.map(&:html_safe)
- end
-
- render :partial => '/gmaps4rails/gmaps4rails',
- :locals => {
- :options => options_with_indifferent_access,
- :js_dependencies => js_dependencies,
- :dom => view_helper.dom_attributes
- }
+ js_dependencies = Gmaps4rails.escape_js_url ? view_helper.js_dependencies_array : view_helper.js_dependencies_array.map(&:html_safe)
+
+ javascript_include_tag(*js_dependencies)
end
+ protected
+
+ def gmaps4rails_map dom, options = {}
+ options.reverse_merge! :style => "width:750px; height:475px;"
+
+ map_script << content_tag(:script, :type => "text/javascript") do
+ raw(options.to_gmaps4rails).html_safe
+ end
+
+ map = case dom.map_provider.to_sym
+ when :mapquest
+ content_tag :div, nil, :id => dom.map_id, :style => options[:style]
+ when :bing
+ content_tag :div, nil, :id => dom.map_id, :class => dom.map_class
+ else
+ content_tag :div, :class => dom.container_class do
+ content_tag :div, nil, :id => dom.map_id, :class => dom.map_class
+ end
+ end
+
+ (map_script + map).html_safe
+ end
end
@@ -21,6 +21,7 @@ def initialize(option_hash)
end
def create_js
+ # @js << "$(function() {"
@js << "#{gmap_id} = new #{ map_constructor };"
@js << "Gmaps.#{js_function_name} = function() {"
@@ -34,7 +35,7 @@ def create_js
@js << "#{gmap_id}.callback();"
@js << "};"
@js << "Gmaps.oldOnload = window.onload;\n window.onload = function() { Gmaps.triggerOldOnload(); Gmaps.loadMaps(); };" if load_map?
-
+ # @js << "}); // ready"
@js * ("\n")
end
@@ -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,6 @@
+map_options:
+ provider: mapquest
+ provider_key: 12345
+ auto_adjust: true
+ center_on_user: true
+ zoom: 5
@@ -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
Oops, something went wrong.