diff --git a/Gemfile b/Gemfile
index ae38ebd..7435644 100644
--- a/Gemfile
+++ b/Gemfile
@@ -65,3 +65,5 @@ group :test do
gem "capybara"
gem "selenium-webdriver"
end
+
+gem "icalendar", "~> 2.10"
diff --git a/Gemfile.lock b/Gemfile.lock
index 4096fda..b1800b7 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -105,6 +105,9 @@ GEM
activesupport (>= 6.1)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
+ icalendar (2.10.1)
+ ice_cube (~> 0.16)
+ ice_cube (0.16.4)
importmap-rails (2.0.1)
actionpack (>= 6.0.0)
activesupport (>= 6.0.0)
@@ -262,6 +265,7 @@ DEPENDENCIES
bootsnap
capybara
debug
+ icalendar (~> 2.10)
importmap-rails
jbuilder
puma (>= 5.0)
diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb
index 007bdb3..53ee762 100644
--- a/app/controllers/events_controller.rb
+++ b/app/controllers/events_controller.rb
@@ -6,6 +6,15 @@ def index
@events = Event.all
end
+ def import
+ files = params[:ics_files].reject(&:blank?)
+ files.each do |file|
+ Event.create_from_ics(file)
+ end
+
+ redirect_to events_path, notice: "Events imported!"
+ end
+
# GET /events/1 or /events/1.json
def show
end
diff --git a/app/models/event.rb b/app/models/event.rb
index f21036b..9d4ae0b 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -1,2 +1,15 @@
class Event < ApplicationRecord
+ def self.create_from_ics(file_path)
+ file = File.open(file_path)
+ calendars = Icalendar::Calendar.parse(file)
+ event = calendars.first.events.first
+ Event.create(
+ starts_at: event.dtstart,
+ ends_at: event.dtend,
+ location: event.location,
+ summary: event.summary.strip,
+ description: event.description,
+ url: event.url
+ )
+ end
end
diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb
index 9cac572..046eafb 100644
--- a/app/views/events/index.html.erb
+++ b/app/views/events/index.html.erb
@@ -1,5 +1,10 @@
<%= notice %>
+<%= form_with url: import_events_path, method: :post do |form| %>
+ <%= form.file_field :ics_files, multiple: true %>
+ <%= form.submit %>
+<% end %>
+
Events
diff --git a/config/routes.rb b/config/routes.rb
index aaffdbe..453d88b 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,9 @@
Rails.application.routes.draw do
- resources :events
+ resources :events do
+ collection do
+ post :import
+ end
+ end
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
diff --git a/test/fixtures/files/Sunday+morning+yoga+in+Antibes+.ics b/test/fixtures/files/Sunday+morning+yoga+in+Antibes+.ics
new file mode 100644
index 0000000..0cde37e
--- /dev/null
+++ b/test/fixtures/files/Sunday+morning+yoga+in+Antibes+.ics
@@ -0,0 +1,49 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Meetup//RemoteApi//EN
+CALSCALE:GREGORIAN
+METHOD:PUBLISH
+X-ORIGINAL-URL:https://www.meetup.com/englishspeakingyoganiceantibes/even
+ ts/299417408/ical/Sunday+morning+yoga+in+Antibes+.ics
+X-WR-CALNAME:Events - Sunday morning yoga in Antibes .ics
+X-MS-OLK-FORCEINSPECTOROPEN:TRUE
+BEGIN:VTIMEZONE
+TZID:Europe/Paris
+TZURL:http://tzurl.org/zoneinfo-outlook/Europe/Paris
+X-LIC-LOCATION:Europe/Paris
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+TZNAME:CEST
+DTSTART:19700329T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+TZNAME:CET
+DTSTART:19701025T030000
+RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20240302T205200Z
+DTSTART;TZID=Europe/Paris:20240303T103000
+DTEND;TZID=Europe/Paris:20240303T113000
+STATUS:CONFIRMED
+SUMMARY:Sunday morning yoga in Antibes
+DESCRIPTION:English Yoga | Nice/Antibes/Monaco\nSunday\, March 3 at 10:30
+ AM\n\nJoin us for some yoga on Sunday morning in Antibes! 🌞✨Accessible
+ to all levels of experience 🙏🏻Price: 15€\n\nhttps://www.meetup.com/en
+ glishspeakingyoganiceantibes/events/299417408/
+CLASS:PUBLIC
+CREATED:20240225T133601Z
+GEO:43.70;7.26
+LOCATION:Plage de la Gravette\, Antibes (Small beach behind Port Vauban\,
+ Antibes\, France)
+URL:https://www.meetup.com/englishspeakingyoganiceantibes/events/29941740
+ 8/
+LAST-MODIFIED:20240225T133630Z
+UID:event_299417408@meetup.com
+END:VEVENT
+END:VCALENDAR
diff --git a/test/fixtures/files/Wednesday+5+km+or+more.ics b/test/fixtures/files/Wednesday+5+km+or+more.ics
new file mode 100644
index 0000000..b2b52c2
--- /dev/null
+++ b/test/fixtures/files/Wednesday+5+km+or+more.ics
@@ -0,0 +1,48 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Meetup//RemoteApi//EN
+CALSCALE:GREGORIAN
+METHOD:PUBLISH
+X-ORIGINAL-URL:https://www.meetup.com/nice-runners/events/299443075/ical/
+ Wednesday+5+km+or+more.ics
+X-WR-CALNAME:Events - Wednesday 5 km or more.ics
+X-MS-OLK-FORCEINSPECTOROPEN:TRUE
+BEGIN:VTIMEZONE
+TZID:Europe/Paris
+TZURL:http://tzurl.org/zoneinfo-outlook/Europe/Paris
+X-LIC-LOCATION:Europe/Paris
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+TZNAME:CEST
+DTSTART:19700329T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+TZNAME:CET
+DTSTART:19701025T030000
+RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20240302T205210Z
+DTSTART;TZID=Europe/Paris:20240304T193000
+DTEND;TZID=Europe/Paris:20240304T210000
+STATUS:CONFIRMED
+SUMMARY:Wednesday 5 km or more
+DESCRIPTION:Nice Runners\nMonday\, March 4 at 7:30 PM\n\nwe meet and run
+ 5 to 10 km. in the group there are different speeds and different levels
+ of preparation and everyone makes the distance they feel. in ...\n\nhtt
+ ps://www.meetup.com/nice-runners/events/299443075/
+CLASS:PUBLIC
+CREATED:20240226T173204Z
+GEO:43.70;7.26
+LOCATION:Ma Nolan's Irish Pub at - Vieux\, Nice (2 Rue Saint François De
+ Paule (Cours Saleya)\, Nice\, France)
+URL:https://www.meetup.com/nice-runners/events/299443075/
+LAST-MODIFIED:20240226T173204Z
+UID:event_jlvnktygcfbgb@meetup.com
+END:VEVENT
+END:VCALENDAR
diff --git a/test/models/event_test.rb b/test/models/event_test.rb
index c8465c1..45e8edb 100644
--- a/test/models/event_test.rb
+++ b/test/models/event_test.rb
@@ -1,7 +1,9 @@
require "test_helper"
class EventTest < ActiveSupport::TestCase
- # test "the truth" do
- # assert true
- # end
+ test "create_from_ics" do
+ file_path = "test/fixtures/files/Sunday+morning+yoga+in+Antibes+.ics"
+ event = Event.create_from_ics(file_path)
+ assert_equal "Sunday morning yoga in Antibes", event.summary
+ end
end