From 32804bf24311c5f76581e9be4a39fd1e038ada55 Mon Sep 17 00:00:00 2001 From: Carlos Daniel Pohlod Date: Wed, 9 Nov 2022 17:15:28 -0300 Subject: [PATCH 1/2] refactored ConferencesController#calendar: separated calendar event creation into an specific service --- app/controllers/conferences_controller.rb | 46 ++++--------- app/services/conference/calendar.rb | 64 ++++++++++++++++++ .../conference/calendar/event_builder.rb | 67 +++++++++++++++++++ config/routes.rb | 2 +- .../conferences_controller_spec.rb | 40 +++++++++++ .../conference/calendar/event_builder_spec.rb | 64 ++++++++++++++++++ 6 files changed, 249 insertions(+), 34 deletions(-) create mode 100644 app/services/conference/calendar.rb create mode 100644 app/services/conference/calendar/event_builder.rb create mode 100644 spec/services/conference/calendar/event_builder_spec.rb diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb index a9dcdd3ba6..22ed42910d 100644 --- a/app/controllers/conferences_controller.rb +++ b/app/controllers/conferences_controller.rb @@ -68,42 +68,22 @@ def show end def calendar + i_calendar = Icalendar::Calendar.new + respond_to do |format| format.ics do - calendar = Icalendar::Calendar.new - Conference.all.each do |conf| - if params[:full] - event_schedules = conf.program.selected_event_schedules( - includes: [{ event: %i[event_type speakers submitter] }] - ) - calendar = icalendar_proposals(calendar, event_schedules.map(&:event), conf) - else - calendar.event do |e| - e.dtstart = conf.start_date - e.dtstart.ical_params = { 'VALUE'=>'DATE' } - e.dtend = conf.end_date - e.dtend.ical_params = { 'VALUE'=>'DATE' } - e.duration = "P#{(conf.end_date - conf.start_date + 1).floor}D" - e.created = conf.created_at - e.last_modified = conf.updated_at - e.summary = conf.title - e.description = conf.description - e.uid = conf.guid - e.url = conference_url(conf.short_title) - v = conf.venue - if v - e.geo = v.latitude, v.longitude if v.latitude && v.longitude - location = '' - location += "#{v.street}, " if v.street - location += "#{v.postalcode} #{v.city}, " if v.postalcode && v.city - location += v.country_name if v.country_name - e.location = location if location - end - end - end + Conference.all.each do |conference| + conference_url = conference_url(conference.short_title) + Conference::Calendar::EventBuilder.call( + conference: conference, + conference_url: conference_url, + calendar: i_calendar, + is_full_calendar: params[:full] + ) end - calendar.publish - render inline: calendar.to_ical + + i_calendar.publish + render inline: i_calendar.to_ical end end end diff --git a/app/services/conference/calendar.rb b/app/services/conference/calendar.rb new file mode 100644 index 0000000000..acd8f05e60 --- /dev/null +++ b/app/services/conference/calendar.rb @@ -0,0 +1,64 @@ +class Conferences::Calendar + private_class_method :new + + def self.call(conference:, is_full_calendar:) + new(conference, is_full_calendar).call + end + + def initialize(conference:, is_full_calendar:) + @calendar = Icalendar::Calendar.new + @conference = conference + @is_full_calendar = is_full_calendar + end + + def not_full_calendar + calendar.event do |e| + default_calendar_params(e) + if @conference.venue + venue_calendar_params(e) + end + end + calendar + end + + def full_calendar + icalendar_proposals(@calendar, event_schedules.map(&:event), @conference) + end + + private + + def default_calendar_params(event) + event.dtstart = @conference.start_date + event.dtstart.ical_params = { 'VALUE'=>'DATE' } + event.dtend = @conference.end_date + event.dtend.ical_params = { 'VALUE'=>'DATE' } + event.duration = "P#{(@conference.end_date - @conference.start_date + 1).floor}D" + event.created = @conference.created_at + event.last_modified = @conference.updated_at + event.summary = @conference.title + event.description = @conference.description + event.uid = @conference.guid + event.url = conference_url(@conference.short_title) + end + + def venue_calendar_params(event) + venue = @conference.venue + event.geo = venue.latitude, venue.longitude if venue.latitude && venue.longitude + location = location(venue) + event.location = location if location + end + + def location(venue) + location = '' + location += "#{venue.street}, " if venue.street + location += "#{venue.postalcode} #{venue.city}, " if venue.postalcode && venue.city + location += venue.country_name if venue.country_name + location + end + + def event_schedules + @conference.program.selected_event_schedules( + includes: [{ event: %i[event_type speakers submitter] }] + ) + end +end diff --git a/app/services/conference/calendar/event_builder.rb b/app/services/conference/calendar/event_builder.rb new file mode 100644 index 0000000000..9ff8f9c48d --- /dev/null +++ b/app/services/conference/calendar/event_builder.rb @@ -0,0 +1,67 @@ +class Conference::Calendar::EventBuilder + include ConferenceHelper + + def self.call(conference:, is_full_calendar:, calendar:, conference_url:) + new(conference:, is_full_calendar:, calendar:, conference_url:).call + end + + def initialize(conference:, is_full_calendar:, calendar:, conference_url:) + @calendar = calendar + @conference_url = conference_url + @conference = conference + @is_full_calendar = is_full_calendar + @venue = conference.venue + end + + def call + return build_full_calendar if is_full_calendar + + build_not_full_calendar + end + + private + attr :conference, :is_full_calendar, :calendar, :conference_url, :venue + + def build_full_calendar + event_schedules = conference.program.selected_event_schedules( + includes: [{ event: %i[event_type speakers submitter] }] + ) + icalendar_proposals(calendar, event_schedules.map(&:event), conference) + end + + def build_not_full_calendar + calendar.event do |event| + build_event_general_informations(event) + build_event_venue(event) if venue + end + calendar + end + + def build_event_general_informations(event) + event.dtstart = conference.start_date + event.dtstart.ical_params = { 'VALUE'=>'DATE' } + event.dtend = conference.end_date + event.dtend.ical_params = { 'VALUE'=>'DATE' } + event.duration = "P#{(conference.end_date - conference.start_date + 1).floor}D" + event.created = conference.created_at + event.last_modified = conference.updated_at + event.summary = conference.title + event.description = conference.description + event.uid = conference.guid + event.url = conference_url + end + + def build_event_venue(event) + event.geo = venue.latitude, venue.longitude if venue.latitude && venue.longitude + location = build_venue_location + event.location = location if location + end + + def build_venue_location + location = '' + location += "#{venue.street}, " if venue.street + location += "#{venue.postalcode} #{venue.city}, " if venue.postalcode && venue.city + location += venue.country_name if venue.country_name + location + end +end diff --git a/config/routes.rb b/config/routes.rb index 5865281de7..f88e97319a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -223,7 +223,7 @@ get '/admin' => redirect('/admin/conferences') - get '/calendar' => 'conferences#calendar' + get '/calendar' => 'conferences#calendar', action: :calendar if ENV.fetch('OSEM_ROOT_CONFERENCE', nil) root to: redirect("/conferences/#{ENV.fetch('OSEM_ROOT_CONFERENCE')}") diff --git a/spec/controllers/conferences_controller_spec.rb b/spec/controllers/conferences_controller_spec.rb index c9a17d14c8..4e59bdcff9 100644 --- a/spec/controllers/conferences_controller_spec.rb +++ b/spec/controllers/conferences_controller_spec.rb @@ -49,4 +49,44 @@ end end + describe 'GET#calendar' do + let(:i_calendar) do + instance_double(Icalendar::Calendar, publish: true, to_ical: true) + end + let!(:conference) { create(:conference) } + let(:params) { { full: double(:full), format: :ics } } + let(:user) { create :user, is_admin: true } + + setup do + user.update!(is_admin: true) + + sign_in user + + allow(Conference::Calendar::EventBuilder) + .to receive(:call) + + allow(Icalendar::Calendar) + .to receive(:new) + .and_return(i_calendar) + end + + it 'calls Conference::Calendar::EventBuilder with correct params' do + expect(Conference::Calendar::EventBuilder) + .to receive(:call) + .with( + conference: conference, + conference_url: conference_url(conference.short_title), + calendar: i_calendar, + is_full_calendar: params[:full].to_s + ) + + get :calendar, params: params + end + + it 'calls calendar#publish' do + expect(i_calendar).to receive(:publish) + + get :calendar, params: params + end + end end diff --git a/spec/services/conference/calendar/event_builder_spec.rb b/spec/services/conference/calendar/event_builder_spec.rb new file mode 100644 index 0000000000..b88b9e7f25 --- /dev/null +++ b/spec/services/conference/calendar/event_builder_spec.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Conference::Calendar::EventBuilder, type: :serializer do + describe '.call' do + let(:conference_url) { 'www.sample.com' } + let!(:calendar) { Icalendar::Calendar.new } + let(:conference) { create :full_conference } + + context 'when is a full calendar' do + let(:proposals_calendar) { double(:proposals_calendar) } + + setup do + allow_any_instance_of(ConferenceHelper) + .to receive(:icalendar_proposals) + .and_return(proposals_calendar) + end + + it 'returns icalendar_proposals' do + result = described_class.call( + conference: conference, + calendar: calendar, + is_full_calendar: true, + conference_url: conference_url + ) + + expect(result).to eq(proposals_calendar) + end + end + + context 'when is a not full calendar' do + let(:venue) { conference.venue } + setup do + venue.update(latitude: '-100', longitude:'-200') + end + + it 'set callendar params' do + calendar = Icalendar::Calendar.new + described_class.call( + conference: conference, + calendar: calendar, + is_full_calendar: false, + conference_url: conference_url + ) + event = calendar.events.first + + expect(event.location).to eq("#{venue.street}, #{venue.postalcode} #{venue.city}, #{venue.country_name}") + expect(event.dtstart).to eq(conference.start_date) + expect(event.dtstart.ical_params).to eq({ 'VALUE'=>'DATE' }) + expect(event.dtend).to eq(conference.end_date) + expect(event.dtend.ical_params).to eq({ 'VALUE'=>'DATE' }) + expect(event.duration.present?).to eq(true) + expect(event.created).to eq(conference.created_at) + expect(event.last_modified).to eq(conference.updated_at) + expect(event.summary).to eq(conference.title) + expect(event.description).to eq(conference.description) + expect(event.uid).to eq(conference.guid) + expect(event.url.value_ical).to eq(conference_url) + expect(event.geo).to eq([conference.venue.latitude.to_f, conference.venue.longitude.to_f]) + end + end + end +end From facf9d7a90e6832790f49974410d0d385543e04b Mon Sep 17 00:00:00 2001 From: Carlos Daniel Pohlod Date: Fri, 11 Nov 2022 14:43:26 -0300 Subject: [PATCH 2/2] removed old calendar service --- app/services/conference/calendar.rb | 64 ----------------------------- 1 file changed, 64 deletions(-) delete mode 100644 app/services/conference/calendar.rb diff --git a/app/services/conference/calendar.rb b/app/services/conference/calendar.rb deleted file mode 100644 index acd8f05e60..0000000000 --- a/app/services/conference/calendar.rb +++ /dev/null @@ -1,64 +0,0 @@ -class Conferences::Calendar - private_class_method :new - - def self.call(conference:, is_full_calendar:) - new(conference, is_full_calendar).call - end - - def initialize(conference:, is_full_calendar:) - @calendar = Icalendar::Calendar.new - @conference = conference - @is_full_calendar = is_full_calendar - end - - def not_full_calendar - calendar.event do |e| - default_calendar_params(e) - if @conference.venue - venue_calendar_params(e) - end - end - calendar - end - - def full_calendar - icalendar_proposals(@calendar, event_schedules.map(&:event), @conference) - end - - private - - def default_calendar_params(event) - event.dtstart = @conference.start_date - event.dtstart.ical_params = { 'VALUE'=>'DATE' } - event.dtend = @conference.end_date - event.dtend.ical_params = { 'VALUE'=>'DATE' } - event.duration = "P#{(@conference.end_date - @conference.start_date + 1).floor}D" - event.created = @conference.created_at - event.last_modified = @conference.updated_at - event.summary = @conference.title - event.description = @conference.description - event.uid = @conference.guid - event.url = conference_url(@conference.short_title) - end - - def venue_calendar_params(event) - venue = @conference.venue - event.geo = venue.latitude, venue.longitude if venue.latitude && venue.longitude - location = location(venue) - event.location = location if location - end - - def location(venue) - location = '' - location += "#{venue.street}, " if venue.street - location += "#{venue.postalcode} #{venue.city}, " if venue.postalcode && venue.city - location += venue.country_name if venue.country_name - location - end - - def event_schedules - @conference.program.selected_event_schedules( - includes: [{ event: %i[event_type speakers submitter] }] - ) - end -end