FIX: Correctly support DiscourseEvent kwargs (#19788)

Fixes the support for kwargs in `DiscourseEvent.trigger()` on Ruby 3, e.g.

```rb
DiscourseEvent.trigger(:before_system_message_sent, message_type: type, recipient: @recipient, post_creator_args: post_creator_args, params: method_params)
```

Fixes https://github.com/discourse/discourse-local-site-contacts
This commit is contained in:
Jarek Radosz 2023-01-09 11:26:39 +01:00 committed by GitHub
parent 56eaf91589
commit ff508d1ae5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 15 deletions

View File

@ -9,9 +9,9 @@ class DiscourseEvent
@events ||= Hash.new { |hash, key| hash[key] = Set.new } @events ||= Hash.new { |hash, key| hash[key] = Set.new }
end end
def self.trigger(event_name, *params) def self.trigger(event_name, *args, **kwargs)
events[event_name].each do |event| events[event_name].each do |event|
event.call(*params) event.call(*args, **kwargs)
end end
end end

View File

@ -1,7 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
RSpec.describe DiscourseEvent do RSpec.describe DiscourseEvent do
describe "#events" do describe "#events" do
it "defaults to {}" do it "defaults to {}" do
begin begin
@ -21,7 +20,6 @@ RSpec.describe DiscourseEvent do
end end
context 'when calling events' do context 'when calling events' do
let(:harvey) { let(:harvey) {
OpenStruct.new( OpenStruct.new(
name: 'Harvey Dent', name: 'Harvey Dent',
@ -42,15 +40,12 @@ RSpec.describe DiscourseEvent do
end end
context 'when event does not exist' do context 'when event does not exist' do
it "does not raise an error" do it "does not raise an error" do
DiscourseEvent.trigger(:missing_event) DiscourseEvent.trigger(:missing_event)
end end
end end
context 'when single event exists' do context 'when single event exists' do
it "doesn't raise an error" do it "doesn't raise an error" do
DiscourseEvent.trigger(:acid_face, harvey) DiscourseEvent.trigger(:acid_face, harvey)
end end
@ -59,11 +54,9 @@ RSpec.describe DiscourseEvent do
DiscourseEvent.trigger(:acid_face, harvey) DiscourseEvent.trigger(:acid_face, harvey)
expect(harvey.name).to eq('Two Face') expect(harvey.name).to eq('Two Face')
end end
end end
context 'when multiple events exist' do context 'when multiple events exist' do
let(:event_handler_2) do let(:event_handler_2) do
Proc.new { |user| user.job = 'Supervillain' } Proc.new { |user| user.job = 'Supervillain' }
end end
@ -84,7 +77,6 @@ RSpec.describe DiscourseEvent do
end end
describe '#all_off' do describe '#all_off' do
let(:event_handler_2) do let(:event_handler_2) do
Proc.new { |user| user.job = 'Supervillain' } Proc.new { |user| user.job = 'Supervillain' }
end end
@ -99,7 +91,20 @@ RSpec.describe DiscourseEvent do
DiscourseEvent.trigger(:acid_face, harvey) # Doesn't change anything DiscourseEvent.trigger(:acid_face, harvey) # Doesn't change anything
expect(harvey.job).to eq('gardening') expect(harvey.job).to eq('gardening')
end end
end
end
it "allows using kwargs" do
begin
handler = Proc.new do |name:, message:|
expect(name).to eq("Supervillain")
expect(message).to eq("Two Face")
end
DiscourseEvent.on(:acid_face, &handler)
DiscourseEvent.trigger(:acid_face, name: "Supervillain", message: "Two Face")
ensure
DiscourseEvent.off(:acid_face, &handler)
end end
end end
end end

View File

@ -4,9 +4,7 @@ require 'system_message'
require 'topic_subtype' require 'topic_subtype'
RSpec.describe SystemMessage do RSpec.describe SystemMessage do
describe '#create' do describe '#create' do
fab!(:admin) { Fabricate(:admin) } fab!(:admin) { Fabricate(:admin) }
fab!(:user) { Fabricate(:user) } fab!(:user) { Fabricate(:user) }
@ -81,12 +79,26 @@ RSpec.describe SystemMessage do
it 'sends event with post object' do it 'sends event with post object' do
system_message = SystemMessage.new(user) system_message = SystemMessage.new(user)
event = DiscourseEvent.track(:system_message_sent) { event = DiscourseEvent.track(:system_message_sent) {
system_message.create(:tl2_promotion_message) system_message.create(:tl2_promotion_message)
} }
expect(event[:event_name]).to eq(:system_message_sent) expect(event[:event_name]).to eq(:system_message_sent)
expect(event[:params].first[:post]).to eq(Post.last) expect(event[:params].first[:post]).to eq(Post.last)
expect(event[:params].first[:message_type]).to eq(:tl2_promotion_message) expect(event[:params].first[:message_type]).to eq(:tl2_promotion_message)
end end
it 'sends an event before the system message is sent' do
system_message = SystemMessage.new(user)
event = DiscourseEvent.track(:before_system_message_sent) {
system_message.create(:tl2_promotion_message)
}
expect(event[:event_name]).to eq(:before_system_message_sent)
expect(event[:params].first[:message_type]).to eq(:tl2_promotion_message)
expect(event[:params].first[:recipient]).to eq(user)
end
end end
end end

View File

@ -1,10 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
module DiscourseEvent::TestHelper module DiscourseEvent::TestHelper
def trigger(event_name, *params) def trigger(event_name, *params, **kwargs)
super(event_name, *params) super(event_name, *params, **kwargs)
if @events_trigger if @events_trigger
params << kwargs if kwargs != {}
@events_trigger << { event_name: event_name, params: params } @events_trigger << { event_name: event_name, params: params }
end end
end end
@ -29,7 +30,6 @@ module DiscourseEvent::TestHelper
events = track_events(event_name, args: args) { yield } events = track_events(event_name, args: args) { yield }
events.first events.first
end end
end end
DiscourseEvent.singleton_class.prepend DiscourseEvent::TestHelper DiscourseEvent.singleton_class.prepend DiscourseEvent::TestHelper