radiant-event_map-extension 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +95 -0
- data/Rakefile +138 -0
- data/VERSION +1 -0
- data/app/controllers/event_venues_controller.rb +50 -0
- data/app/views/event_venues/_event.html.haml +20 -0
- data/app/views/event_venues/_venue.html.haml +23 -0
- data/app/views/event_venues/index.html.haml +17 -0
- data/app/views/event_venues/index.js.erb +55 -0
- data/app/views/events/_views.html.haml +11 -0
- data/config/routes.rb +8 -0
- data/cucumber.yml +1 -0
- data/db/migrate/20100311101802_lat_long.rb +20 -0
- data/db/migrate/20100311105231_get_geocodes.rb +17 -0
- data/event_map_extension.rb +19 -0
- data/features/support/env.rb +16 -0
- data/features/support/paths.rb +14 -0
- data/lib/angle_conversions.rb +9 -0
- data/lib/grid_ref.rb +279 -0
- data/lib/mappable.rb +63 -0
- data/lib/tasks/event_map_extension_tasks.rake +28 -0
- data/pkg/radiant-event_map-extension-1.0.1.gem +0 -0
- data/public/images/event_calendar/event_shadow.png +0 -0
- data/public/images/event_calendar/one_event.png +0 -0
- data/public/images/event_calendar/several_events.png +0 -0
- data/public/javascript/markerclusterer.js +735 -0
- data/public/stylesheets/sass/map.sass +11 -0
- data/radiant-event_map-extension.gemspec +79 -0
- data/spec/lib/grid_ref_spec.rb +90 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +36 -0
- metadata +140 -0
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Event Map Extension for Radiant
|
2
|
+
|
3
|
+
This extension adds mapping to the [event_calendar](http://github.com/radiant/radiant-event-calendar-extension). It will geocode your events automatically based on the address of the venue, or you can supply a postal code, UK postcode or grid reference for greater precision.
|
4
|
+
|
5
|
+
Events can be displayed on a google map and you can create links to bing or google maps that display the location of each event.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Should be straightforward:
|
10
|
+
|
11
|
+
script/extension install event_map
|
12
|
+
|
13
|
+
or as a gem:
|
14
|
+
|
15
|
+
gem install radiant-event_map-extension
|
16
|
+
|
17
|
+
## Requirements
|
18
|
+
|
19
|
+
* [event_calendar](http://github.com/radiant/radiant-event-calendar-extension) extension
|
20
|
+
* [layouts](http://github.com/squaretalent/radiant-layouts-extension) or [share_layouts](http://github.com/radiant/radiant-share-layouts-extension) extension
|
21
|
+
* [geokit](http://geokit.rubyforge.org/) gem
|
22
|
+
|
23
|
+
## Configuration
|
24
|
+
|
25
|
+
There is one required config setting:
|
26
|
+
|
27
|
+
* `event_map.layout` is the name of the layout used by the controller
|
28
|
+
|
29
|
+
## Basic Usage
|
30
|
+
|
31
|
+
### Linking to maps
|
32
|
+
|
33
|
+
We override the `url` method of EventVenue to return a map link if no other url is defined. The format of those links is determined by the link template stored in the config setting `event_map.link_format`. The markers :lat, :lng and :title will be replaced with the the correct value for each event venue.
|
34
|
+
|
35
|
+
There are also two shortcuts:
|
36
|
+
|
37
|
+
* 'google' is the default and equivalent to `http://maps.google.com/maps?q=:lat+:lng+(:title)` and will drop a pin on a google map.
|
38
|
+
* 'bing' is equivalent to `http://www.bing.com/maps/?v=2&cp=:lat~:lng&rtp=~pos.:lat_:lng_:title&lvl=15&sty=s&eo=0`, which will display a 1:25000 ordnance survey map (if you're in the UK) with a destination flag at your chosen point.
|
39
|
+
|
40
|
+
### Displaying a map page
|
41
|
+
|
42
|
+
Create a layout that includes a `map_canvas` div and these page parts:
|
43
|
+
|
44
|
+
* `map_js` is required. It brings in the javascripts (and can be used in the header or at the end of the page as you prefer)
|
45
|
+
* `title` is the page title and can also be shown with `r:title`
|
46
|
+
* `faceting` here only gives the option to remove any date filters that have been applied. If you add the `taggable_events` extension it gets more useful.
|
47
|
+
|
48
|
+
Here's a starting point:
|
49
|
+
|
50
|
+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
51
|
+
<head>
|
52
|
+
<title><r:title /></title>
|
53
|
+
<r:content part="map_js" />
|
54
|
+
</head>
|
55
|
+
<body>
|
56
|
+
<h1 id="pagetitle"><r:title /></h1>
|
57
|
+
<r:content part="faceting" />
|
58
|
+
<div id="map_canvas" style="width: 600px; height 400px;"></div>
|
59
|
+
</body>
|
60
|
+
</html>
|
61
|
+
|
62
|
+
Make sure that `Radiant::Config['event_map.layout']` matches exactly the _name_ of this layout.
|
63
|
+
|
64
|
+
### javascript compatibility
|
65
|
+
|
66
|
+
The map javascript is generated by the EventVenuesController using `app/views/event_venues/index.js.erb`. It provides a `build_map_and_markers` method and the minimal jQuery hook required to populate #map_canvas when the DOM loads.
|
67
|
+
|
68
|
+
If you're not using jQuery you should find it straightforward to call `build_map_and_markers(div element)` from another script, and in that case you don't have to use our naming scheme either.
|
69
|
+
|
70
|
+
### JSON interface
|
71
|
+
|
72
|
+
If you don't want to use the included scripts, you can skip that whole mechanism and work with the event data instead. EventVenuesController provides a simple JSON interface. Usually it's at /map and looks for addresses like this:
|
73
|
+
|
74
|
+
/map everything
|
75
|
+
/map/2010 events in 2010
|
76
|
+
/map/2010/12/ events in December 2010
|
77
|
+
/map/2010/12/12 events on 12 December 2010
|
78
|
+
|
79
|
+
If you're using `taggable_events` then we also inherit the tag-faceting interface here.
|
80
|
+
|
81
|
+
The data returned looks like this:
|
82
|
+
|
83
|
+
{
|
84
|
+
|
85
|
+
}
|
86
|
+
|
87
|
+
## Bugs and features
|
88
|
+
|
89
|
+
[Github issues](http://github.com/spanner/radiant-event_map-extension/issues) please, or for little things an email or github message is fine.
|
90
|
+
|
91
|
+
## Author & Copyright
|
92
|
+
|
93
|
+
Copyright 2008-2010 Will at spanner.org.
|
94
|
+
|
95
|
+
Released under the same terms as Radiant and/or Rails.
|
data/Rakefile
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gem|
|
4
|
+
gem.name = "radiant-event_map-extension"
|
5
|
+
gem.summary = %Q{Google mapping for events in the radiant CMS}
|
6
|
+
gem.description = %Q{Further extends the event_calendar extension to allow easy google mapping with automatic geolocation based on event venues}
|
7
|
+
gem.email = "will@spanner.org"
|
8
|
+
gem.homepage = "http://github.com/radiant/radiant-event_map-extension"
|
9
|
+
gem.authors = ["spanner"]
|
10
|
+
gem.add_dependency "geokit"
|
11
|
+
gem.add_dependency "radiant", ">= 0.9.0"
|
12
|
+
gem.add_dependency "radiant-event_calendar-extension"
|
13
|
+
end
|
14
|
+
rescue LoadError
|
15
|
+
puts "Jeweler (or a dependency) not available. This is only required if you plan to package event_map as a gem."
|
16
|
+
end
|
17
|
+
|
18
|
+
# In rails 1.2, plugins aren't available in the path until they're loaded.
|
19
|
+
# Check to see if the rspec plugin is installed first and require
|
20
|
+
# it if it is. If not, use the gem version.
|
21
|
+
|
22
|
+
# Determine where the RSpec plugin is by loading the boot
|
23
|
+
unless defined? RADIANT_ROOT
|
24
|
+
ENV["RAILS_ENV"] = "test"
|
25
|
+
case
|
26
|
+
when ENV["RADIANT_ENV_FILE"]
|
27
|
+
require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
|
28
|
+
when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
|
29
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
|
30
|
+
else
|
31
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'rake'
|
36
|
+
require 'rake/rdoctask'
|
37
|
+
require 'rake/testtask'
|
38
|
+
|
39
|
+
rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
|
40
|
+
$LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
|
41
|
+
require 'spec/rake/spectask'
|
42
|
+
require 'cucumber'
|
43
|
+
require 'cucumber/rake/task'
|
44
|
+
|
45
|
+
# Cleanup the RADIANT_ROOT constant so specs will load the environment
|
46
|
+
Object.send(:remove_const, :RADIANT_ROOT)
|
47
|
+
|
48
|
+
extension_root = File.expand_path(File.dirname(__FILE__))
|
49
|
+
|
50
|
+
task :default => :spec
|
51
|
+
task :stats => "spec:statsetup"
|
52
|
+
|
53
|
+
desc "Run all specs in spec directory"
|
54
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
55
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
56
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
57
|
+
end
|
58
|
+
|
59
|
+
task :features => 'spec:integration'
|
60
|
+
|
61
|
+
namespace :spec do
|
62
|
+
desc "Run all specs in spec directory with RCov"
|
63
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
64
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
65
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
66
|
+
t.rcov = true
|
67
|
+
t.rcov_opts = ['--exclude', 'spec', '--rails']
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "Print Specdoc for all specs"
|
71
|
+
Spec::Rake::SpecTask.new(:doc) do |t|
|
72
|
+
t.spec_opts = ["--format", "specdoc", "--dry-run"]
|
73
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
74
|
+
end
|
75
|
+
|
76
|
+
[:models, :controllers, :views, :helpers].each do |sub|
|
77
|
+
desc "Run the specs under spec/#{sub}"
|
78
|
+
Spec::Rake::SpecTask.new(sub) do |t|
|
79
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
80
|
+
t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
desc "Run the Cucumber features"
|
85
|
+
Cucumber::Rake::Task.new(:integration) do |t|
|
86
|
+
t.fork = true
|
87
|
+
t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
|
88
|
+
# t.feature_pattern = "#{extension_root}/features/**/*.feature"
|
89
|
+
t.profile = "default"
|
90
|
+
end
|
91
|
+
|
92
|
+
# Setup specs for stats
|
93
|
+
task :statsetup do
|
94
|
+
require 'code_statistics'
|
95
|
+
::STATS_DIRECTORIES << %w(Model\ specs spec/models)
|
96
|
+
::STATS_DIRECTORIES << %w(View\ specs spec/views)
|
97
|
+
::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
|
98
|
+
::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
|
99
|
+
::CodeStatistics::TEST_TYPES << "Model specs"
|
100
|
+
::CodeStatistics::TEST_TYPES << "View specs"
|
101
|
+
::CodeStatistics::TEST_TYPES << "Controller specs"
|
102
|
+
::CodeStatistics::TEST_TYPES << "Helper specs"
|
103
|
+
::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
|
104
|
+
end
|
105
|
+
|
106
|
+
namespace :db do
|
107
|
+
namespace :fixtures do
|
108
|
+
desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
|
109
|
+
task :load => :environment do
|
110
|
+
require 'active_record/fixtures'
|
111
|
+
ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
|
112
|
+
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
|
113
|
+
Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
desc 'Generate documentation for the event_map extension.'
|
121
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
122
|
+
rdoc.rdoc_dir = 'rdoc'
|
123
|
+
rdoc.title = 'EventMapExtension'
|
124
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
125
|
+
rdoc.rdoc_files.include('README')
|
126
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
127
|
+
end
|
128
|
+
|
129
|
+
# For extensions that are in transition
|
130
|
+
desc 'Test the event_map extension.'
|
131
|
+
Rake::TestTask.new(:test) do |t|
|
132
|
+
t.libs << 'lib'
|
133
|
+
t.pattern = 'test/**/*_test.rb'
|
134
|
+
t.verbose = true
|
135
|
+
end
|
136
|
+
|
137
|
+
# Load any custom rakefiles for extension
|
138
|
+
Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.1.0
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# We inherit from EventsController to share subsetting functionality
|
2
|
+
# All we do here is organise that information by venue.
|
3
|
+
|
4
|
+
class EventVenuesController < EventsController
|
5
|
+
helper_method :venues, :events_at_venue
|
6
|
+
radiant_layout { |controller| controller.layout_for :event_map }
|
7
|
+
|
8
|
+
def index
|
9
|
+
respond_to do |format|
|
10
|
+
format.html { }
|
11
|
+
format.js {
|
12
|
+
render :layout => false
|
13
|
+
}
|
14
|
+
format.json {
|
15
|
+
render :json => venue_events.to_json
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# event_finder is defined in EventsController
|
21
|
+
|
22
|
+
def events
|
23
|
+
@events ||= all_events
|
24
|
+
end
|
25
|
+
|
26
|
+
def venues
|
27
|
+
@venues ||= events.map(&:event_venue).compact.uniq
|
28
|
+
end
|
29
|
+
|
30
|
+
# events are stashed in venue buckets to avoid returning to the database
|
31
|
+
|
32
|
+
def events_at_venue(venue)
|
33
|
+
venue_events[venue.id]
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def venue_events
|
39
|
+
return @venue_events if @venue_events
|
40
|
+
@venue_events = {}
|
41
|
+
events.each do |e|
|
42
|
+
if e.event_venue
|
43
|
+
@venue_events[e.event_venue.id] ||= []
|
44
|
+
@venue_events[e.event_venue.id].push(e)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
@venue_events
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
- without_title ||= false
|
2
|
+
|
3
|
+
- if event
|
4
|
+
.map_event
|
5
|
+
- unless without_title
|
6
|
+
%h3.event
|
7
|
+
= link_to event.title, event.url
|
8
|
+
|
9
|
+
%p.date
|
10
|
+
%strong
|
11
|
+
= event.summarize_period
|
12
|
+
- if event.event_venue
|
13
|
+
at
|
14
|
+
= link_to event.event_venue.title, event.event_venue.url
|
15
|
+
- else
|
16
|
+
at
|
17
|
+
= event.location
|
18
|
+
|
19
|
+
%p.description
|
20
|
+
= event.short_description
|
@@ -0,0 +1,23 @@
|
|
1
|
+
- if venue
|
2
|
+
- if events = events_at_venue(venue)
|
3
|
+
.map_venue
|
4
|
+
- if events.length == 1
|
5
|
+
= render :partial => 'event', :object => events.first
|
6
|
+
- else
|
7
|
+
%h3
|
8
|
+
Events at
|
9
|
+
= link_to venue.title, venue.url
|
10
|
+
%ul
|
11
|
+
- remainder = events.slice!(4, 10000)
|
12
|
+
- events.each do |event|
|
13
|
+
%li
|
14
|
+
%strong
|
15
|
+
= link_to event.title, event.url
|
16
|
+
on
|
17
|
+
= event.date
|
18
|
+
- if remainder && remainder.any?
|
19
|
+
%li
|
20
|
+
and
|
21
|
+
= remainder.length
|
22
|
+
more events...
|
23
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
- content_for :title do
|
2
|
+
Events
|
3
|
+
= list_description
|
4
|
+
|
5
|
+
- content_for :faceting do
|
6
|
+
= render :partial => 'events/faceting'
|
7
|
+
|
8
|
+
- content_for :map_js do
|
9
|
+
%script{:src => "http://maps.google.com/maps/api/js?sensor=false"}
|
10
|
+
%script{:src => "#{url_for(calendar_parameters.merge(:format => :js))}"}
|
11
|
+
|
12
|
+
/ deprecated older syntax probably unknown to anyone but me
|
13
|
+
- content_for :head do
|
14
|
+
%script{:src => "http://maps.google.com/maps/api/js?sensor=false"}
|
15
|
+
%script{:src => "#{url_for(calendar_parameters.merge(:format => :js))}"}
|
16
|
+
|
17
|
+
= render :partial => 'events/other_page_parts'
|
@@ -0,0 +1,55 @@
|
|
1
|
+
if(typeof jQuery == 'function') {
|
2
|
+
jQuery.fn.populate_map = function() {
|
3
|
+
this.each(function() { build_map_and_markers(this); });
|
4
|
+
};
|
5
|
+
|
6
|
+
jQuery(function() {
|
7
|
+
jQuery("#map_canvas").populate_map();
|
8
|
+
});
|
9
|
+
}
|
10
|
+
|
11
|
+
function build_map_and_markers(element) {
|
12
|
+
if (element != null) {
|
13
|
+
var map = new google.maps.Map(element, {mapTypeId: google.maps.MapTypeId.ROADMAP});
|
14
|
+
var bounds = new google.maps.LatLngBounds();
|
15
|
+
var one_icon = new google.maps.MarkerImage('/images/event_calendar/one_event.png',
|
16
|
+
new google.maps.Size(26,45),
|
17
|
+
new google.maps.Point(0,0),
|
18
|
+
new google.maps.Point(7, 45));
|
19
|
+
var several_icon = new google.maps.MarkerImage('/images/event_calendar/several_events.png',
|
20
|
+
new google.maps.Size(26,45),
|
21
|
+
new google.maps.Point(0,0),
|
22
|
+
new google.maps.Point(9, 45));
|
23
|
+
var one_shadow = new google.maps.MarkerImage('/images/event_calendar/event_shadow.png',
|
24
|
+
new google.maps.Size(60, 44),
|
25
|
+
new google.maps.Point(0,0),
|
26
|
+
new google.maps.Point(8, 45));
|
27
|
+
var several_shadow = new google.maps.MarkerImage('/images/event_calendar/event_shadow.png',
|
28
|
+
new google.maps.Size(60, 44),
|
29
|
+
new google.maps.Point(0,0),
|
30
|
+
new google.maps.Point(5, 45));
|
31
|
+
<% venues.each do |venue| %>
|
32
|
+
add_marker(map, {
|
33
|
+
title : "<%= escape_javascript(venue.title) %>",
|
34
|
+
image : <%= events_at_venue(venue).length > 1 ? "several_icon" : "one_icon" %>,
|
35
|
+
shadow : <%= events_at_venue(venue).length > 1 ? "several_shadow" : "one_shadow" %>,
|
36
|
+
position : new google.maps.LatLng("<%= venue.lat %>","<%= venue.lng %>"),
|
37
|
+
description : "<%= escape_javascript(render :partial => 'venue', :object => venue) %>"
|
38
|
+
});
|
39
|
+
bounds.extend(new google.maps.LatLng("<%= venue.lat %>","<%= venue.lng %>"));
|
40
|
+
<% end %>
|
41
|
+
map.fitBounds(bounds);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
function add_marker (map, mark) {
|
46
|
+
var marker = new google.maps.Marker({ map : map, position : mark['position'], title : mark['title'], icon : mark['image'], shadow : mark['shadow'] });
|
47
|
+
var infowindow = new google.maps.InfoWindow({ content : mark['description'] , maxWidth : 400 });
|
48
|
+
google.maps.event.addListener(marker, 'click', function() { infowindow.open(map, marker); });
|
49
|
+
}
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
%span.calendar_views
|
2
|
+
%br
|
3
|
+
View as
|
4
|
+
= link_to("map", eventmap_url(calendar_parameters))
|
5
|
+
or
|
6
|
+
= link_to("calendar", calendar_url(calendar_parameters)) + "."
|
7
|
+
Stay up to date with
|
8
|
+
= link_to("RSS", calendar_url(calendar_parameters.merge(:format => :rss)))
|
9
|
+
or
|
10
|
+
= link_to("calendar feed", calendar_url(calendar_parameters.merge(:format => :ics, :protocol => 'webcal://', :only_path => false)))
|
11
|
+
|
data/config/routes.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
ActionController::Routing::Routes.draw do |map|
|
2
|
+
map.with_options :controller => 'event_venues', :action => 'index' do |m|
|
3
|
+
m.eventmap "/map.:format"
|
4
|
+
m.eventmap_year "/map/:year.:format"
|
5
|
+
m.eventmap_month "/map/:year/:month.:format"
|
6
|
+
m.eventmap_day "/map/:year/:month/:mday.:format"
|
7
|
+
end
|
8
|
+
end
|
data/cucumber.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
default: --format progress features --tags ~@proposed,~@in_progress
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class LatLong < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :events, :lat, :string
|
4
|
+
add_column :events, :lng, :string
|
5
|
+
add_column :event_venues, :lat, :string
|
6
|
+
add_column :event_venues, :lng, :string
|
7
|
+
add_index :events, [:lat, :lng]
|
8
|
+
add_index :event_venues, [:lat, :lng]
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
remove_column :events, :lat
|
14
|
+
remove_column :events, :lng
|
15
|
+
remove_column :event_venues, :lat
|
16
|
+
remove_column :event_venues, :lng
|
17
|
+
remove_index :events, [:lat, :lng]
|
18
|
+
remove_index :event_venues, [:lat, :lng]
|
19
|
+
end
|
20
|
+
end
|