gmaps4rails 0.8.8 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/{array.rb → extensions/array.rb} +3 -0
- data/lib/{hash.rb → extensions/hash.rb} +5 -1
- data/lib/gmaps4rails.rb +6 -7
- data/lib/gmaps4rails/acts_as_gmappable.rb +85 -0
- data/lib/gmaps4rails/base.rb +170 -0
- data/lib/{gmaps4rails_helper.rb → helper/gmaps4rails_helper.rb} +4 -0
- data/public/javascripts/gmaps4rails.js +201 -164
- data/test/dummy/app/controllers/users_controller.rb +4 -0
- data/test/dummy/app/models/user.rb +2 -1
- data/test/dummy/config/routes.rb +2 -0
- data/test/dummy/spec/base/base_spec.rb +2 -2
- data/test/dummy/spec/javascripts/support/jasmine_config.rb +23 -0
- data/test/dummy/spec/javascripts/support/jasmine_runner.rb +20 -0
- data/test/dummy/spec/models/user_spec.rb +198 -313
- data/test/dummy/spec/{factories.rb → support/factories.rb} +0 -5
- data/test/dummy/spec/support/matchers.rb +7 -0
- metadata +18 -13
- data/lib/acts_as_gmappable/base.rb +0 -209
- data/test/dummy/spec/controllers/users_controller_spec.rb +0 -57
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'rspec/expectations'
|
2
|
+
|
3
|
+
RSpec::Matchers.define :have_same_position_as do |position_hash|
|
4
|
+
match do |object|
|
5
|
+
object.send(object.gmaps4rails_options[:lat_column]) == position_hash[:latitude] && object.send(object.gmaps4rails_options[:lng_column]) == position_hash[:longitude]
|
6
|
+
end
|
7
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gmaps4rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 59
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 9
|
9
|
+
- 0
|
10
|
+
version: 0.9.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Benjamin Roth
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-
|
19
|
+
date: 2011-07-02 00:00:00 +02:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -46,13 +46,14 @@ extra_rdoc_files:
|
|
46
46
|
- README.rdoc
|
47
47
|
files:
|
48
48
|
- app/views/gmaps4rails/_gmaps4rails.html.erb
|
49
|
-
- lib/
|
50
|
-
- lib/
|
49
|
+
- lib/extensions/array.rb
|
50
|
+
- lib/extensions/hash.rb
|
51
51
|
- lib/generators/gmaps4rails/install_generator.rb
|
52
52
|
- lib/generators/templates/README
|
53
53
|
- lib/gmaps4rails.rb
|
54
|
-
- lib/
|
55
|
-
- lib/
|
54
|
+
- lib/gmaps4rails/acts_as_gmappable.rb
|
55
|
+
- lib/gmaps4rails/base.rb
|
56
|
+
- lib/helper/gmaps4rails_helper.rb
|
56
57
|
- public/images/marker.png
|
57
58
|
- public/javascripts/gmaps4rails.js
|
58
59
|
- public/stylesheets/gmaps4rails.css
|
@@ -81,11 +82,13 @@ files:
|
|
81
82
|
- test/dummy/db/schema.rb
|
82
83
|
- test/dummy/db/seeds.rb
|
83
84
|
- test/dummy/spec/base/base_spec.rb
|
84
|
-
- test/dummy/spec/
|
85
|
-
- test/dummy/spec/
|
85
|
+
- test/dummy/spec/javascripts/support/jasmine_config.rb
|
86
|
+
- test/dummy/spec/javascripts/support/jasmine_runner.rb
|
86
87
|
- test/dummy/spec/models/user_spec.rb
|
87
88
|
- test/dummy/spec/requests/users_spec.rb
|
88
89
|
- test/dummy/spec/spec_helper.rb
|
90
|
+
- test/dummy/spec/support/factories.rb
|
91
|
+
- test/dummy/spec/support/matchers.rb
|
89
92
|
has_rdoc: true
|
90
93
|
homepage: http://github.com/apneadiving/Google-Maps-for-Rails
|
91
94
|
licenses: []
|
@@ -144,8 +147,10 @@ test_files:
|
|
144
147
|
- test/dummy/db/schema.rb
|
145
148
|
- test/dummy/db/seeds.rb
|
146
149
|
- test/dummy/spec/base/base_spec.rb
|
147
|
-
- test/dummy/spec/
|
148
|
-
- test/dummy/spec/
|
150
|
+
- test/dummy/spec/javascripts/support/jasmine_config.rb
|
151
|
+
- test/dummy/spec/javascripts/support/jasmine_runner.rb
|
149
152
|
- test/dummy/spec/models/user_spec.rb
|
150
153
|
- test/dummy/spec/requests/users_spec.rb
|
151
154
|
- test/dummy/spec/spec_helper.rb
|
155
|
+
- test/dummy/spec/support/factories.rb
|
156
|
+
- test/dummy/spec/support/matchers.rb
|
@@ -1,209 +0,0 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
require 'uri'
|
3
|
-
require 'crack'
|
4
|
-
require 'logger'
|
5
|
-
|
6
|
-
module Gmaps4rails
|
7
|
-
|
8
|
-
class GeocodeStatus < StandardError; end
|
9
|
-
class GeocodeNetStatus < StandardError; end
|
10
|
-
class GeocodeInvalidQuery < StandardError; end
|
11
|
-
class DirectionStatus < StandardError; end
|
12
|
-
class DirectionNetStatus < StandardError; end
|
13
|
-
class DirectionInvalidQuery < StandardError; end
|
14
|
-
|
15
|
-
def Gmaps4rails.create_json(object)
|
16
|
-
unless object.send(object.gmaps4rails_options[:lat_column]).blank? && object.send(object.gmaps4rails_options[:lng_column]).blank?
|
17
|
-
"{#{Gmaps4rails.description(object)}#{Gmaps4rails.title(object)}#{Gmaps4rails.sidebar(object)}\"longitude\": \"#{object.send(object.gmaps4rails_options[:lng_column])}\", \"latitude\": \"#{object.send(object.gmaps4rails_options[:lat_column])}\"#{Gmaps4rails.picture(object)}},\n"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def Gmaps4rails.description(object)
|
22
|
-
return "\"description\": \"#{object.gmaps4rails_infowindow}\", " if object.respond_to?("gmaps4rails_infowindow")
|
23
|
-
end
|
24
|
-
|
25
|
-
def Gmaps4rails.title(object)
|
26
|
-
return "\"title\": \"#{object.gmaps4rails_title}\", " if object.respond_to?("gmaps4rails_title")
|
27
|
-
end
|
28
|
-
|
29
|
-
def Gmaps4rails.sidebar(object)
|
30
|
-
return "\"sidebar\": \"#{object.gmaps4rails_sidebar}\"," if object.respond_to?("gmaps4rails_sidebar")
|
31
|
-
end
|
32
|
-
|
33
|
-
def Gmaps4rails.picture(object)
|
34
|
-
return ", \"picture\": \"#{object.gmaps4rails_marker_picture['picture']}\", \"width\": \"#{object.gmaps4rails_marker_picture['width']}\", \"height\": \"#{object.gmaps4rails_marker_picture['height']}\"" if object.respond_to?("gmaps4rails_marker_picture")
|
35
|
-
end
|
36
|
-
|
37
|
-
def Gmaps4rails.geocode(address, lang="en", raw = false)
|
38
|
-
if address.nil? || address.empty?
|
39
|
-
raise Gmaps4rails::GeocodeInvalidQuery, "You must provide an address"
|
40
|
-
else #coordinates are valid
|
41
|
-
geocoder = "http://maps.googleapis.com/maps/api/geocode/json?language=#{lang}&address="
|
42
|
-
output = "&sensor=false"
|
43
|
-
#send request to the google api to get the lat/lng
|
44
|
-
request = geocoder + address + output
|
45
|
-
url = URI.escape(request)
|
46
|
-
resp = Net::HTTP.get_response(URI.parse(url))
|
47
|
-
#parse result if result received properly
|
48
|
-
if resp.is_a?(Net::HTTPSuccess)
|
49
|
-
#parse the json
|
50
|
-
parse = Crack::JSON.parse(resp.body)
|
51
|
-
#logger.debug "Google geocoding. Address: #{address}. Result: #{resp.body}"
|
52
|
-
#check if google went well
|
53
|
-
if parse["status"] == "OK"
|
54
|
-
return parse if raw == true
|
55
|
-
array = []
|
56
|
-
parse["results"].each do |result|
|
57
|
-
array << {
|
58
|
-
:lat => result["geometry"]["location"]["lat"],
|
59
|
-
:lng => result["geometry"]["location"]["lng"],
|
60
|
-
:matched_address => result["formatted_address"],
|
61
|
-
:bounds => result["geometry"]["bounds"],
|
62
|
-
:full_data => result
|
63
|
-
}
|
64
|
-
end
|
65
|
-
return array
|
66
|
-
else #status != OK
|
67
|
-
raise Gmaps4rails::GeocodeStatus, "The address you passed seems invalid, status was: #{parse["status"]}.
|
68
|
-
Request was: #{request}"
|
69
|
-
end #end parse status
|
70
|
-
|
71
|
-
else #if not http success
|
72
|
-
raise Gmaps4rails::GeocodeNetStatus, "The request sent to google was invalid (not http success): #{request}.
|
73
|
-
Response was: #{resp}"
|
74
|
-
end #end resp test
|
75
|
-
end # end address valid
|
76
|
-
end #end geocode
|
77
|
-
|
78
|
-
#output could be raw, pretty or clean
|
79
|
-
def Gmaps4rails.destination(start_end, options={}, output="pretty")
|
80
|
-
if start_end["from"].nil? || start_end["to"].empty?
|
81
|
-
raise Gmaps4rails::DirectionInvalidQuery, "Origin and destination must be provided in a hash as first argument"
|
82
|
-
else #great, we have stuff to work with
|
83
|
-
geocoder = "http://maps.googleapis.com/maps/api/directions/json?origin=#{start_end["from"]}&destination=#{start_end["to"]}"
|
84
|
-
#if value is an Array, it means it contains the waypoints, otherwise it's chained normally
|
85
|
-
dest_options = options.empty? ? "" : "&" + options.map {|k,v| v.is_a?(Array) ? k + "=" + v * ("|") : k + "=" + v }*("&")
|
86
|
-
#send request to the google api to get the directions
|
87
|
-
request = geocoder + dest_options + "&sensor=false"
|
88
|
-
url = URI.escape(request)
|
89
|
-
resp = Net::HTTP.get_response(URI.parse(url))
|
90
|
-
#parse result if result received properly
|
91
|
-
if resp.is_a?(Net::HTTPSuccess)
|
92
|
-
#parse the json
|
93
|
-
parse = Crack::JSON.parse(resp.body)
|
94
|
-
#check if google went well
|
95
|
-
if parse["status"] == "OK"
|
96
|
-
legs = []
|
97
|
-
#Each element in the legs array specifies a single leg of the journey from the origin to the destination in the calculated route
|
98
|
-
parse["routes"].first["legs"].each do |leg|
|
99
|
-
#delete coded polyline elements from legs and store it in polylines to make output cleaner
|
100
|
-
polylines = leg["steps"].map {|step| step.delete("polyline")} if output == "pretty" || output == "clean"
|
101
|
-
legs << {
|
102
|
-
"duration" => { "text" => leg["duration"]["text"], "value" => leg["duration"]["value"].to_f },
|
103
|
-
"distance" => { "text" => leg["distance"]["text"], "value" => leg["distance"]["value"].to_f },
|
104
|
-
"steps" => leg["steps"]
|
105
|
-
}
|
106
|
-
if output == "pretty"
|
107
|
-
#polylines contain levels data, which are not that useful.
|
108
|
-
polylines.map{|poly| poly.delete("levels")}
|
109
|
-
#create valid json from all polylines, this could be directly passed to javascript for display
|
110
|
-
json = polylines.map { |poly| {"coded_array" => poly["points"]} }.to_json
|
111
|
-
#merge results in legs
|
112
|
-
legs.last.merge!({ "polylines" => json })
|
113
|
-
end
|
114
|
-
end
|
115
|
-
return legs
|
116
|
-
else #status != OK
|
117
|
-
raise Gmaps4rails::DirectionStatus, "The query you passed seems invalid, status was: #{parse["status"]}.
|
118
|
-
Request was: #{request}"
|
119
|
-
end #end parse status
|
120
|
-
else #if not http success
|
121
|
-
raise Gmaps4rails::DirectionNetStatus, "The request sent to google was invalid (not http success): #{request}.
|
122
|
-
Response was: #{resp}"
|
123
|
-
end #end resp test
|
124
|
-
end # end origin + destination exist
|
125
|
-
end #end destination
|
126
|
-
|
127
|
-
|
128
|
-
def Gmaps4rails.filter(data)
|
129
|
-
return data if data.is_a?(Numeric) || data.is_a?(TrueClass) || data.is_a?(FalseClass)
|
130
|
-
"'#{data}'"
|
131
|
-
end
|
132
|
-
|
133
|
-
module ActsAsGmappable
|
134
|
-
|
135
|
-
extend ActiveSupport::Concern
|
136
|
-
|
137
|
-
module InstanceMethods
|
138
|
-
|
139
|
-
def process_geocoding
|
140
|
-
#to prevent geocoding each time a save is made
|
141
|
-
return true if gmaps4rails_options[:check_process] == true && self.send(gmaps4rails_options[:checker]) == true
|
142
|
-
begin
|
143
|
-
coordinates = Gmaps4rails.geocode(self.send(gmaps4rails_options[:address]), gmaps4rails_options[:language])
|
144
|
-
rescue GeocodeStatus, GeocodeInvalidQuery #address was invalid, add error to base.
|
145
|
-
errors[gmaps4rails_options[:address]] << gmaps4rails_options[:msg] if gmaps4rails_options[:validation]
|
146
|
-
rescue GeocodeNetStatus => e #connection error, No need to prevent save.
|
147
|
-
logger.warn(e)
|
148
|
-
#TODO add customization here?
|
149
|
-
else #if no exception
|
150
|
-
self.send(gmaps4rails_options[:lng_column]+"=", coordinates.first[:lng]) if self.respond_to?(gmaps4rails_options[:lng_column]+"=")
|
151
|
-
self.send(gmaps4rails_options[:lat_column]+"=", coordinates.first[:lat]) if self.respond_to?(gmaps4rails_options[:lat_column]+"=")
|
152
|
-
unless gmaps4rails_options[:normalized_address].nil?
|
153
|
-
self.send(gmaps4rails_options[:normalized_address].to_s+"=", coordinates.first[:matched_address])
|
154
|
-
end
|
155
|
-
# Call the callback method to let the user do what he wants with the data
|
156
|
-
self.send(gmaps4rails_options[:callback], coordinates.first[:full_data]) unless gmaps4rails_options[:callback].nil?
|
157
|
-
if gmaps4rails_options[:check_process] == true
|
158
|
-
self[gmaps4rails_options[:checker]] = true
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
def to_gmaps4rails
|
164
|
-
json = "["
|
165
|
-
json += Gmaps4rails.create_json(self).to_s.chop.chop #removes the extra comma
|
166
|
-
json += "]"
|
167
|
-
end
|
168
|
-
|
169
|
-
end
|
170
|
-
|
171
|
-
module ClassMethods
|
172
|
-
|
173
|
-
def acts_as_gmappable args = {}
|
174
|
-
unless args[:process_geocoding] == false
|
175
|
-
validate :process_geocoding
|
176
|
-
end
|
177
|
-
|
178
|
-
#instance method
|
179
|
-
define_method "gmaps4rails_options" do
|
180
|
-
{
|
181
|
-
:lat_column => args[:lat] || "latitude",
|
182
|
-
:lng_column => args[:lng] || "longitude",
|
183
|
-
:check_process => args[:check_process].nil? ? true : args[:check_process],
|
184
|
-
:checker => args[:checker] || "gmaps",
|
185
|
-
:msg => args[:msg] || "Address invalid",
|
186
|
-
:validation => args[:validation].nil? ? true : args[:validation],
|
187
|
-
:normalized_address => args[:normalized_address],
|
188
|
-
:address => args[:address] || "gmaps4rails_address",
|
189
|
-
:callback => args[:callback],
|
190
|
-
:language => args[:language] || "en"
|
191
|
-
#TODO: address as a proc?
|
192
|
-
}
|
193
|
-
end
|
194
|
-
|
195
|
-
include InstanceMethods
|
196
|
-
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
end #ActsAsGmappable
|
201
|
-
end
|
202
|
-
|
203
|
-
ActiveSupport.on_load(:active_record) do
|
204
|
-
ActiveRecord::Base.send(:include, Gmaps4rails::ActsAsGmappable)
|
205
|
-
end
|
206
|
-
#::ActiveRecord::Base.send :include, Gmaps4rails::ActsAsGmappable
|
207
|
-
# Mongoid::Document::ClassMethods.class_eval do
|
208
|
-
# include Gmaps4rails::ActsAsGmappable::Base
|
209
|
-
# end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
# require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
#
|
3
|
-
# describe UsersController do
|
4
|
-
# fixtures :all
|
5
|
-
# render_views
|
6
|
-
#
|
7
|
-
# it "index action should render index template" do
|
8
|
-
# get :index
|
9
|
-
# response.should render_template(:index)
|
10
|
-
# end
|
11
|
-
#
|
12
|
-
# it "show action should render show template" do
|
13
|
-
# get :show, :id => User.first
|
14
|
-
# response.should render_template(:show)
|
15
|
-
# end
|
16
|
-
#
|
17
|
-
# it "new action should render new template" do
|
18
|
-
# get :new
|
19
|
-
# response.should render_template(:new)
|
20
|
-
# end
|
21
|
-
#
|
22
|
-
# it "create action should render new template when model is invalid" do
|
23
|
-
# User.any_instance.stubs(:valid?).returns(false)
|
24
|
-
# post :create
|
25
|
-
# response.should render_template(:new)
|
26
|
-
# end
|
27
|
-
#
|
28
|
-
# it "create action should redirect when model is valid" do
|
29
|
-
# User.any_instance.stubs(:valid?).returns(true)
|
30
|
-
# post :create
|
31
|
-
# response.should redirect_to(user_url(assigns[:user]))
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# it "edit action should render edit template" do
|
35
|
-
# get :edit, :id => User.first
|
36
|
-
# response.should render_template(:edit)
|
37
|
-
# end
|
38
|
-
#
|
39
|
-
# it "update action should render edit template when model is invalid" do
|
40
|
-
# User.any_instance.stubs(:valid?).returns(false)
|
41
|
-
# put :update, :id => User.first
|
42
|
-
# response.should render_template(:edit)
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
# it "update action should redirect when model is valid" do
|
46
|
-
# User.any_instance.stubs(:valid?).returns(true)
|
47
|
-
# put :update, :id => User.first
|
48
|
-
# response.should redirect_to(user_url(assigns[:user]))
|
49
|
-
# end
|
50
|
-
#
|
51
|
-
# it "destroy action should destroy model and redirect to index action" do
|
52
|
-
# user = User.first
|
53
|
-
# delete :destroy, :id => user
|
54
|
-
# response.should redirect_to(users_url)
|
55
|
-
# User.exists?(user.id).should be_false
|
56
|
-
# end
|
57
|
-
# end
|