Skip to content

Instantly share code, notes, and snippets.

@joegaudet
Last active May 23, 2019 20:21
Show Gist options
  • Select an option

  • Save joegaudet/aed4a0b0abadf4e461267023f9c9ed48 to your computer and use it in GitHub Desktop.

Select an option

Save joegaudet/aed4a0b0abadf4e461267023f9c9ed48 to your computer and use it in GitHub Desktop.
Better Wisper Usage
module Ordering
module Events
class CartCleared < ::Events::Event
values do
attribute :order_id, Integer
attribute :group_order_member_ids, Array[Integer]
attribute :order_item_ids, Array[Integer]
end
end
end
end
module Ordering
module Commands
class ClearCart < ::Commands::Command
dependency :find_order, Queries::Id.klass(Order)
dependency :save, ::Commands::SaveRecord
dependency :emit, ::Events::Emitter
def call(order_id)
order = find_order.(order_id)
group_order_member_ids = order.group_order_member_ids
order_item_ids = order.order_item_ids
in_transaction do
order.group_order_members.destroy_all
order.order_items.destroy_all
end
emit.(
Ordering::Events::CartCleared.build(
order_id: order.id,
order_item_ids: order_item_ids,
group_order_member_ids: group_order_member_ids
)
)
save.(order)
end
end
end
end
module Events
class Emitter < ::Values::Base
include Wisper::Publisher
def call(event)
broadcast(event.event_name, event.attributes)
end
end
end
module Events
class Event < ::Values::Base
include Wisper::Publisher
def self.build(attrs)
new(attrs)
end
def event_name
self.class.event_name
end
def self.event_name(event_name = nil)
@event_name = event_name unless event_name.nil?
@event_name
end
end
end
module Events
module Handler
def self.included(base)
base.extend(ClassMethods)
# Ensure when eager loading / reloading, we don't subscribe twice
unless Rails.env.test?
Wisper.unsubscribe(base)
end
end
module ClassMethods
def handle(klass, &block)
Wisper.subscribe(self, async: true, on: klass.event_name)
# add static handler
define_singleton_method(klass.event_name) do |event|
# build klass from schema
event = klass.(event)
raise ArgumentError, "Event #{event.event_name} was not valid" unless event.valid?
new.instance_eval(&block)
end
end
end
end
end
module Ordering
class InvoiceJob < ApplicationJob
include ::Events::Handler
handle Ordering::Events:CartCleared do |event|
Ordering::InvoiceJob.perform_later(event.order_id)
end
end
end
class PusherJob < ApplicationJob
include ::Events::Handler
dependency :pusher_service, PusherService
# handlers are bound to an instance scope
handle Ordering::Events::CartCleared do |event|
pusher.publish("ee.food.orders.#{event.order_id}.order-events", "cart_cleared")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment