Skip to content

Commit

Permalink
Merge pull request #246 from apneadiving/mongoid_adapter
Browse files Browse the repository at this point in the history
Mongoid adapter
  • Loading branch information
apneadiving committed Aug 6, 2012
2 parents 485b185 + 19144c3 commit 2553a31
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 33 deletions.
3 changes: 1 addition & 2 deletions .travis.yml
Expand Up @@ -3,8 +3,7 @@ rvm:
- 1.8.7
- 1.9.2
- 1.9.3
gemfile:
- Gemfile

before_script: 'cd spec/dummy/; rake db:migrate RAILS_ENV=test; cd ../..'
script: 'rspec spec'
after_script: 'bundle exec guard-jasmine -u http://localhost:8888/'
8 changes: 8 additions & 0 deletions Gemfile.lock
Expand Up @@ -91,7 +91,14 @@ GEM
treetop (~> 1.4.8)
method_source (0.7.1)
mime-types (1.18)
mongoid (3.0.3)
activemodel (~> 3.1)
moped (~> 1.1)
origin (~> 1.0)
tzinfo (~> 0.3.22)
moped (1.2.0)
multi_json (1.2.0)
origin (1.0.4)
polyglot (0.3.3)
pry (0.9.8.4)
coderay (~> 1.0.5)
Expand Down Expand Up @@ -172,6 +179,7 @@ DEPENDENCIES
guard-spork
jasmine
jquery-rails
mongoid (~> 3)
pry
rails (~> 3.2.1)
rspec-rails
Expand Down
8 changes: 8 additions & 0 deletions README.rdoc
Expand Up @@ -66,6 +66,14 @@ Create a migration and add the following fields to your table (here users):
add_column :users, :longitude, :float #you can change the name, see wiki
add_column :users, :gmaps, :boolean #not mandatory, see wiki

== Basic configuration: Non-relational DB

Mongoid example:

acts_as_gmappable :position => :location

field :location, :type => Array

== How to?
=== QuickStart!
In your controller:
Expand Down
1 change: 1 addition & 0 deletions gmaps4rails.gemspec
Expand Up @@ -17,6 +17,7 @@ Gem::Specification.new do |s|

s.add_development_dependency "rails", "~> 3.2.1"
s.add_development_dependency "sqlite3"
s.add_development_dependency "mongoid", "~> 3" if RUBY_VERSION == "1.9.3"
s.add_development_dependency 'jquery-rails'
s.add_development_dependency "rspec-rails"
s.add_development_dependency 'database_cleaner'
Expand Down
34 changes: 15 additions & 19 deletions lib/gmaps4rails/acts_as_gmappable.rb
@@ -1,26 +1,18 @@
module Gmaps4rails
module ActsAsGmappable

def self.included base
base.send :include, InstanceMethods
base.send :extend, ClassMethods
extend ActiveSupport::Concern

# This is a validation method which triggers the geocoding and save its results
def process_geocoding
Gmaps4rails::ModelHandler.new(self, gmaps4rails_options).retrieve_coordinates
end

module InstanceMethods

# This is a validation method which triggers the geocoding and save its results
def process_geocoding
Gmaps4rails::ModelHandler.new(self, gmaps4rails_options).retrieve_coordinates
end

# creates json for one instance
def to_gmaps4rails(&block)
json = "["
object_json = Gmaps4rails.create_json(self, &block)
json << object_json.to_s unless object_json.nil?
json << "]"
end

# creates json for one instance
def to_gmaps4rails(&block)
json = "["
object_json = Gmaps4rails.create_json(self, &block)
json << object_json.to_s unless object_json.nil?
json << "]"
end

module ClassMethods
Expand All @@ -38,6 +30,10 @@ def acts_as_gmappable args = {}

:lat_column => args[:lat] || "latitude",
:lng_column => args[:lng] || "longitude",

# purposefully no default.
# Leaving out the :position arg means we are using the default lat/lng to store coordinates
:position => args[:position],

:msg => args[:msg] || "Address invalid",
:validation => args[:validation].nil? ? true : args[:validation],
Expand Down
1 change: 1 addition & 0 deletions lib/gmaps4rails/base.rb
Expand Up @@ -20,6 +20,7 @@ module Gmaps4rails
autoload :Geocoder, 'gmaps4rails/api_wrappers/geocoder'
autoload :Direction, 'gmaps4rails/api_wrappers/direction'
autoload :Places, 'gmaps4rails/api_wrappers/places'
autoload :ObjectAccessor, 'gmaps4rails/object_accessor'

mattr_accessor :http_proxy

Expand Down
29 changes: 24 additions & 5 deletions lib/gmaps4rails/json_builder.rb
Expand Up @@ -25,9 +25,12 @@ module Gmaps4rails
# end
#
class JsonBuilder

delegate :position, :lat_column, :lng_column, :to => :@options

def initialize(object)
@object, @json_hash, @custom_json = object, Hash.new, nil
@options = OpenStruct.new @object.gmaps4rails_options
end

def process(&block)
Expand Down Expand Up @@ -72,17 +75,21 @@ def model_attributes
:description => :gmaps4rails_infowindow,
:title => :gmaps4rails_title,
:sidebar => :gmaps4rails_sidebar,
:marker_picture => :gmaps4rails_marker_picture,
:lat => @object.gmaps4rails_options[:lat_column],
:lng => @object.gmaps4rails_options[:lng_column]
}
:marker_picture => :gmaps4rails_marker_picture
}.merge(coordinates_attributes)
end

def coordinates_attributes
position_from_array? ? {:position => position } : {:lat => lat_column, :lng => lng_column}
end

def handle_model_methods
model_attributes.each do |json_name, method_name|
if @object.respond_to? method_name
if json_name == :marker_picture
@json_hash.merge!(@object.send(method_name)) unless @json_hash.has_key? "picture"
elsif json_name == :position
@json_hash.merge!(:lat => lat, :lng => lng)
else
@json_hash[json_name] = @object.send(method_name) unless @json_hash.has_key? json_name
end
Expand All @@ -108,14 +115,26 @@ def return_json
end

def compliant?
!(@object.send(@object.gmaps4rails_options[:lat_column]).blank? && @object.send(@object.gmaps4rails_options[:lng_column]).blank?)
!(lat.blank? && lng.blank?)
end

def handle_block(&block)
block_result = yield(@object, self)
@custom_json = block_result unless block_result == true
end

def position_from_array?
position #if gmaps4rails_options[:position] is filled, means user is indicating an array
end

def lat
position_from_array? ? @object.send("#{position}")[0] : @object.send("#{lat_column}")
end

def lng
position_from_array? ? @object.send("#{position}")[1] : @object.send("#{lng_column}")
end

end

end
34 changes: 28 additions & 6 deletions lib/gmaps4rails/model_handler.rb
Expand Up @@ -4,9 +4,9 @@ class ModelHandler

attr_accessor :options, :object

delegate :process_geocoding, :check_process, :checker, :lat_column, :lng_column, :msg, :validation,
delegate :process_geocoding, :check_process, :checker, :lat_column, :lng_column, :position, :msg, :validation,
:language, :protocol, :address, :callback, :normalized_address,
:to => :@options
:to => :options

def initialize(object, gmaps4rails_options)
@options = ::OpenStruct.new(gmaps4rails_options)
Expand All @@ -16,19 +16,41 @@ def initialize(object, gmaps4rails_options)
# saves coordinates according to the various options
def retrieve_coordinates
return if prevent_geocoding?
checked_coordinates do
object.send("#{lng_column}=", coordinates.first[:lng])
object.send("#{lat_column}=", coordinates.first[:lat])
checked_coordinates do
position? ? set_position : set_lat_lng
# save normalized address if required
object.send("#{normalized_address}=", coordinates.first[:matched_address]) if normalized_address
# Call the callback method to let the user do what he wants with the data
object.send(callback, coordinates.first[:full_data]) if callback
object.send callback, coordinates.first[:full_data] if callback
# update checker if required
object.send("#{checker}=", true) if check_geocoding?
end
end

private

# sets array for non relationnal db
def set_position
object.send("#{position}=", [lat, lng])
end

#sets regular columns
def set_lat_lng
object.send("#{lng_column}=", lng)
object.send("#{lat_column}=", lat)
end

def lat
coordinates.first[:lat]
end

def lng
coordinates.first[:lng]
end

def position?
position
end

def checked_coordinates(&block)
yield if coordinates
Expand Down
16 changes: 16 additions & 0 deletions spec/dummy/app/models/place.rb
@@ -0,0 +1,16 @@
if RUBY_VERSION == "1.9.3"

require 'mongoid'

class Place
include Mongoid::Document
include Gmaps4rails::ActsAsGmappable

acts_as_gmappable :address => :address, :position => :pos

field :pos, :type => Array
field :address, :type => String
field :gmaps, :type => Boolean
end

end
16 changes: 16 additions & 0 deletions spec/factories/place_factory.rb
@@ -0,0 +1,16 @@
FactoryGirl.define do
factory :place do

trait :paris do
address "Paris, France"
end

trait :invalid do
address "home"
end

address "Toulon, France"

factory :place_paris, :traits => [:paris]
end
end
35 changes: 35 additions & 0 deletions spec/models/place_spec.rb
@@ -0,0 +1,35 @@
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

let(:place) { Factory(:place) }
let(:invalid_place) { Factory.build(:invalid_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')
place.pos.should_not be_nil
place.should have_same_position_as TOULON
end
end
end

end
32 changes: 31 additions & 1 deletion spec/support/matchers.rb
@@ -1,4 +1,5 @@
require 'rspec/expectations'
require 'ostruct'

def has_same_content_as?(actual, expected)
case actual
Expand Down Expand Up @@ -27,9 +28,38 @@ def has_same_content_as?(actual, expected)
end
end

class PositionMatcher
attr_reader :object, :position_hash
delegate :position, :lat_column, :lng_column, :to => :@options

def initialize object, position_hash
@object, @position_hash = object, position_hash
@options = ::OpenStruct.new object.gmaps4rails_options
end

def same_pos?
position_hash[:latitude] == lat && position_hash[:longitude] == lng
end

protected

def lat
position ? object.send("#{position}")[0] : object.send("#{lat_column}")
end

def lng
position ? object.send("#{position}")[1] : object.send("#{lng_column}")
end

end

def position_matcher object, position_hash
PositionMatcher.new object, position_hash
end

RSpec::Matchers.define :have_same_position_as do |position_hash|
match do |object|
object.send(object.gmaps4rails_options[:lat_column]) == position_hash[:latitude] && object.send(object.gmaps4rails_options[:lng_column]) == position_hash[:longitude]
position_matcher(object, position_hash).same_pos?
end
end

Expand Down

0 comments on commit 2553a31

Please sign in to comment.