diff --git a/app/components/event_card_component.html.erb b/app/components/event_card_component.html.erb index 915a6efad..d8251e631 100644 --- a/app/components/event_card_component.html.erb +++ b/app/components/event_card_component.html.erb @@ -1,4 +1,4 @@ -<% cache [@event.cache_key_with_version, I18n.locale, :v2] do %> +<% cache [@event.cache_key_with_version, I18n.locale, :v3] do %>
diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 08c7e8163..e44839606 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -196,9 +196,13 @@ def load_events(rows) (hash[row['event_type']] ||= []) << row['id'].to_i end + # workshop_host must be preloaded: eager_loading it alongside :sponsors + # routes both through the workshop_sponsors table in one join, and the + # host scope then binds to the wrong table alias — the host comes back + # nil or points at a non-host sponsor. Same pattern as Listable.most_recent. workshops = Workshop.eager_load(:sponsors, :organisers, - workshop_host: :sponsor, chapter: { permissions: :members }) + .preload(workshop_host: :sponsor) .where(id: grouped['Workshop']) .to_a.index_by(&:id) meetings = Meeting.eager_load(:venue, :organisers).where(id: grouped['Meeting']) diff --git a/app/presenters/event_presenter.rb b/app/presenters/event_presenter.rb index b00f500b1..d2614ea52 100644 --- a/app/presenters/event_presenter.rb +++ b/app/presenters/event_presenter.rb @@ -30,7 +30,7 @@ def short_description end def organisers - @organisers ||= model.organisers.to_a + @organisers ||= model.organisers.to_a.sort_by { |organiser| organiser.name.to_s } end def month diff --git a/app/presenters/workshop_presenter.rb b/app/presenters/workshop_presenter.rb index e26252a4d..84148ef7b 100644 --- a/app/presenters/workshop_presenter.rb +++ b/app/presenters/workshop_presenter.rb @@ -31,11 +31,12 @@ def venue @venue ||= model.host end + def sponsors + model.sponsors.sort_by { |sponsor| sponsor.name.to_s } + end + def organisers - @organisers ||= begin - orgs = model.organisers.to_a - orgs.any? ? orgs : chapter_organisers - end + @organisers ||= (model.organisers.to_a.presence || chapter_organisers).sort_by { |organiser| organiser.name.to_s } end def attendees_checklist diff --git a/spec/controllers/events_controller_spec.rb b/spec/controllers/events_controller_spec.rb index 306fa616b..6b0a6b029 100644 --- a/spec/controllers/events_controller_spec.rb +++ b/spec/controllers/events_controller_spec.rb @@ -244,4 +244,65 @@ expect(response).to have_http_status(:ok) end end + + describe '#load_events' do + let(:chapter) { Fabricate(:chapter) } + let(:host_sponsor) { Fabricate(:sponsor, name: 'Zulu GmbH') } + let(:extra_sponsor) { Fabricate(:sponsor, name: 'Alpha AG') } + + def rows_for(workshops) + workshops.map { |w| { 'event_type' => 'Workshop', 'id' => w.id } } + end + + it 'loads the host sponsor as workshop_host for every workshop' do + workshops = Fabricate.times(6, :workshop_no_sponsor, chapter:) + workshops.each do |workshop| + Fabricate(:workshop_sponsor, workshop:, sponsor: host_sponsor, host: true) + Fabricate(:workshop_sponsor, workshop:, sponsor: extra_sponsor, host: false) + end + + loaded = controller.send(:load_events, rows_for(workshops)) + + expect(loaded.map { |e| e.workshop_host&.sponsor&.id }).to all(eq(host_sponsor.id)) + end + + it 'lists all sponsors of a workshop' do + workshop = Fabricate(:workshop_no_sponsor, chapter:) + Fabricate(:workshop_sponsor, workshop:, sponsor: host_sponsor, host: true) + Fabricate(:workshop_sponsor, workshop:, sponsor: extra_sponsor, host: false) + + loaded = controller.send(:load_events, rows_for([workshop])) + + expect(loaded.first.sponsors).to contain_exactly(host_sponsor, extra_sponsor) + end + + it 'renders sponsors and organisers in name order' do + workshop = Fabricate(:workshop_no_sponsor, chapter:) + Fabricate(:workshop_sponsor, workshop:, sponsor: host_sponsor, host: true) + Fabricate(:workshop_sponsor, workshop:, sponsor: extra_sponsor, host: false) + anton = Fabricate(:member, name: 'Anton') + zora = Fabricate(:member, name: 'Zora') + anton.add_role :organiser, workshop + zora.add_role :organiser, workshop + + loaded = controller.send(:load_events, rows_for([workshop])) + presenter = EventPresenter.decorate(loaded.first) + + expect(presenter.sponsors.map(&:name)).to eq(['Alpha AG', 'Zulu GmbH']) + expect(presenter.organisers.map(&:name)).to eq(%w[Anton Zora]) + end + + it 'sorts organisers with blank names without raising' do + workshop = Fabricate(:workshop_no_sponsor, chapter:) + anton = Fabricate(:member, name: 'Anton') + anton.update_column(:name, nil) + anton.add_role :organiser, workshop + Fabricate(:member, name: 'Zora').add_role :organiser, workshop + + loaded = controller.send(:load_events, rows_for([workshop])) + presenter = EventPresenter.decorate(loaded.first) + + expect(presenter.organisers.map(&:name)).to eq([nil, 'Zora']) + end + end end