pubsub_on_rails 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +17 -0
- data/LICENSE.md +21 -0
- data/lib/pub_sub.rb +2 -0
- data/lib/pub_sub/domain.rb +23 -0
- data/lib/pub_sub/domain_event.rb +15 -0
- data/lib/pub_sub/domain_event_handler.rb +27 -0
- data/lib/pub_sub/emit.rb +16 -0
- data/lib/pub_sub/event_class_factory.rb +59 -0
- data/lib/pub_sub/event_emission.rb +44 -0
- data/lib/pub_sub/linter.rb +39 -0
- data/lib/pub_sub/payload_attribute.rb +31 -0
- data/lib/pub_sub/subscriptions.rb +50 -0
- data/lib/pub_sub/testing.rb +3 -0
- data/lib/pub_sub/testing/event_data_helper.rb +12 -0
- data/lib/pub_sub/testing/subscription_helpers.rb +24 -0
- data/lib/pub_sub/version.rb +3 -0
- data/lib/pubsub_on_rails.rb +9 -0
- metadata +117 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: e5aeb57501923d0faf35b735734647ab6880660059475126dc4aae2bce6f6d59
         | 
| 4 | 
            +
              data.tar.gz: 7da45ebcbc7c928f93c4960c02bed54585dfe3bfa9c91906bba7070e8f8b45a5
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: 730b60a32e1f9873e783f9f029f60f1cf9ec105d55e001afba968dd80eee794f74f2f685fe944419780dc381d64a43157f6f51c660022d70766a1d9b7532fe94
         | 
| 7 | 
            +
              data.tar.gz: 69c30741019142f5124e9e98f58723efad81fb74ec918a1ffd7a27822dedd66c74f5db888ac4c97f5cf0296ad84e19cc1ceae46ad1858730740048d666bad954
         | 
    
        data/Gemfile
    ADDED
    
    
    
        data/Gemfile.lock
    ADDED
    
    
    
        data/LICENSE.md
    ADDED
    
    | @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            # MIT LICENSE
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Copyright (c) 2019 Stevo <b.kosmowski@selleo.com>
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         | 
| 6 | 
            +
            of this software and associated documentation files (the "Software"), to deal
         | 
| 7 | 
            +
            in the Software without restriction, including without limitation the rights
         | 
| 8 | 
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         | 
| 9 | 
            +
            copies of the Software, and to permit persons to whom the Software is
         | 
| 10 | 
            +
            furnished to do so, subject to the following conditions:
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            The above copyright notice and this permission notice shall be included in
         | 
| 13 | 
            +
            all copies or substantial portions of the Software.
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         | 
| 16 | 
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         | 
| 17 | 
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         | 
| 18 | 
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         | 
| 19 | 
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         | 
| 20 | 
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
         | 
| 21 | 
            +
            THE SOFTWARE.
         | 
    
        data/lib/pub_sub.rb
    ADDED
    
    
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            module PubSub
         | 
| 2 | 
            +
              module Domain
         | 
| 3 | 
            +
                def method_missing(event_or_method_name, *event_data)
         | 
| 4 | 
            +
                  if handler_name(event_or_method_name)
         | 
| 5 | 
            +
                    const_get(handler_name(event_or_method_name)).new(*event_data).call!
         | 
| 6 | 
            +
                  else
         | 
| 7 | 
            +
                    super
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def handler_name(event_name)
         | 
| 12 | 
            +
                  return nil unless event_name.to_s.start_with?(/[a-z_]+__/)
         | 
| 13 | 
            +
                  "#{event_name.to_s.camelize}Handler"
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def respond_to_missing?(event_or_method_name, include_private = false)
         | 
| 17 | 
            +
                  return super unless handler_name(event_or_method_name)
         | 
| 18 | 
            +
                  const_get(handler_name(event_or_method_name))
         | 
| 19 | 
            +
                rescue NameError
         | 
| 20 | 
            +
                  super
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            module PubSub
         | 
| 2 | 
            +
              class DomainEvent < Dry::Struct
         | 
| 3 | 
            +
                include Wisper::Publisher
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def broadcast!
         | 
| 6 | 
            +
                  broadcast(event_name, attributes)
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                private
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def event_name
         | 
| 12 | 
            +
                  self.class.name.underscore.sub('/', '__').chomp('_event')
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            module PubSub
         | 
| 2 | 
            +
              class DomainEventHandler
         | 
| 3 | 
            +
                def initialize(*args)
         | 
| 4 | 
            +
                  @event_data_hash = args.extract_options!
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def call
         | 
| 8 | 
            +
                  raise NotImplementedError
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def call!
         | 
| 12 | 
            +
                  call if process_event?
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                private
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                attr_reader :event_data_hash
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def process_event?
         | 
| 20 | 
            +
                  true
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def event_data
         | 
| 24 | 
            +
                  @event_data ||= OpenStruct.new(event_data_hash)
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
    
        data/lib/pub_sub/emit.rb
    ADDED
    
    | @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            require 'pub_sub/event_class_factory'
         | 
| 2 | 
            +
            require 'pub_sub/event_emission'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module PubSub
         | 
| 5 | 
            +
              module Emit
         | 
| 6 | 
            +
                def emit(event_name, explicit_payload = {})
         | 
| 7 | 
            +
                  event_class = EventClassFactory.build(
         | 
| 8 | 
            +
                    event_name,
         | 
| 9 | 
            +
                    domain_name: self.class.name.deconstantize.demodulize,
         | 
| 10 | 
            +
                    abstract_event_class: explicit_payload.delete(:abstract_event_class)
         | 
| 11 | 
            +
                  )
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  EventEmission.new(event_class, explicit_payload, self).call
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -0,0 +1,59 @@ | |
| 1 | 
            +
            module PubSub
         | 
| 2 | 
            +
              class EventClassFactory
         | 
| 3 | 
            +
                EventClassDoesNotExist = Class.new(StandardError)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def self.build(event_name, domain_name: nil, abstract_event_class: nil)
         | 
| 6 | 
            +
                  new(
         | 
| 7 | 
            +
                    event_name,
         | 
| 8 | 
            +
                    domain_name: domain_name,
         | 
| 9 | 
            +
                    abstract_event_class: abstract_event_class
         | 
| 10 | 
            +
                  ).build_event_class
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def initialize(event_name, domain_name:, abstract_event_class:)
         | 
| 14 | 
            +
                  @event_name = event_name.to_s
         | 
| 15 | 
            +
                  @abstract_event_class = abstract_event_class
         | 
| 16 | 
            +
                  @domain_name = domain_name
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def build_event_class
         | 
| 20 | 
            +
                  event_class = event_class_name.safe_constantize
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  return event_class unless event_class.nil?
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  if abstract_event_class.nil?
         | 
| 25 | 
            +
                    raise(EventClassDoesNotExist, event_class_name)
         | 
| 26 | 
            +
                  else
         | 
| 27 | 
            +
                    register_new_event_class
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                private
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                attr_reader :event_name, :abstract_event_class, :domain_name
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def register_new_event_class
         | 
| 36 | 
            +
                  event_class_namespace.const_set(event_class_name.demodulize, Class.new(abstract_event_class))
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def event_class_namespace
         | 
| 40 | 
            +
                  event_class_name.deconstantize.constantize
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def event_name_includes_domain?
         | 
| 44 | 
            +
                  event_name.include?('__')
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def event_name_with_domain
         | 
| 48 | 
            +
                  if event_name_includes_domain?
         | 
| 49 | 
            +
                    event_name.to_s.sub('__', '/')
         | 
| 50 | 
            +
                  else
         | 
| 51 | 
            +
                    "#{domain_name}/#{event_name}"
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def event_class_name
         | 
| 56 | 
            +
                  @event_class_name ||= "#{event_name_with_domain}_event".classify
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
            end
         | 
| @@ -0,0 +1,44 @@ | |
| 1 | 
            +
            require 'pub_sub/payload_attribute'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module PubSub
         | 
| 4 | 
            +
              class EventEmission
         | 
| 5 | 
            +
                EventPayloadArgumentMissing = Class.new(StandardError)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def initialize(event_class, explicit_payload, context)
         | 
| 8 | 
            +
                  @event_class = event_class
         | 
| 9 | 
            +
                  @explicit_payload = explicit_payload
         | 
| 10 | 
            +
                  @context = context
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def call
         | 
| 14 | 
            +
                  event_class.new(full_payload).broadcast!
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                private
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                attr_reader :event_class, :explicit_payload, :context
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def event_payload_attribute_names
         | 
| 22 | 
            +
                  event_class.attribute_names
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                # rubocop:disable Metrics/MethodLength
         | 
| 26 | 
            +
                def full_payload
         | 
| 27 | 
            +
                  event_payload_attribute_names.each_with_object({}) do |attribute_name, result|
         | 
| 28 | 
            +
                    result[attribute_name] = PayloadAttribute.new(attribute_name, explicit_payload, context).get
         | 
| 29 | 
            +
                  rescue PayloadAttribute::CannotEvaluate => cannot_evaluate_error
         | 
| 30 | 
            +
                    if event_class.schema[attribute_name.to_sym].default?
         | 
| 31 | 
            +
                      next
         | 
| 32 | 
            +
                    else
         | 
| 33 | 
            +
                      raise(
         | 
| 34 | 
            +
                        EventPayloadArgumentMissing,
         | 
| 35 | 
            +
                        "Event [#{event_class.name}] expects [#{attribute_name}] payload attribute to be" \
         | 
| 36 | 
            +
                          " either exposed as [#{cannot_evaluate_error.message}] method in emitting object" \
         | 
| 37 | 
            +
                          ' or provided as argument'
         | 
| 38 | 
            +
                      )
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
                # rubocop:enable Metrics/MethodLength
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
            end
         | 
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            class Linter
         | 
| 2 | 
            +
              MissingSubscriptions = Class.new(StandardError)
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              def initialize(config)
         | 
| 5 | 
            +
                @config = config
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              def lint!
         | 
| 9 | 
            +
                raise MissingSubscriptions, error_message if missing_subscriptions.present?
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              private
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              def error_message
         | 
| 15 | 
            +
                "The following subscriptions are missing: \n#{missing_subscriptions.join("\n")}"
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def missing_subscriptions
         | 
| 19 | 
            +
                (handlers_list - subscriptions_list)
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              attr_reader :config
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def subscriptions_list
         | 
| 25 | 
            +
                config.flat_map do |domain_name, subscriptions|
         | 
| 26 | 
            +
                  subscriptions.keys.map do |event_name|
         | 
| 27 | 
            +
                    "#{domain_name}/#{event_name.sub('__', '_')}"
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              def handlers_list
         | 
| 33 | 
            +
                Dir[Rails.root.join('app/event_handlers/*/*.rb')].map do |file_path|
         | 
| 34 | 
            +
                  file_path.
         | 
| 35 | 
            +
                    sub("#{Rails.root}/app/event_handlers/", '').
         | 
| 36 | 
            +
                    sub('_handler.rb', '')
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
            end
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            module PubSub
         | 
| 2 | 
            +
              class PayloadAttribute
         | 
| 3 | 
            +
                CannotEvaluate = Class.new(StandardError)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(attribute_name, explicit_payload, context)
         | 
| 6 | 
            +
                  @attribute_name = attribute_name
         | 
| 7 | 
            +
                  @explicit_payload = explicit_payload
         | 
| 8 | 
            +
                  @context = context
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def get
         | 
| 12 | 
            +
                  return explicit_payload.fetch(attribute_name) if explicit_payload.key?(attribute_name)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  identifier? ? context.send(getter_name)&.id : context.send(getter_name)
         | 
| 15 | 
            +
                rescue NoMethodError
         | 
| 16 | 
            +
                  raise CannotEvaluate, getter_name
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                private
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                attr_reader :attribute_name, :explicit_payload, :context
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def identifier?
         | 
| 24 | 
            +
                  !context.respond_to?(attribute_name, true) && attribute_name.to_s.end_with?('_id')
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def getter_name
         | 
| 28 | 
            +
                  identifier? ? attribute_name.to_s.chomp('_id') : attribute_name
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            require 'pub_sub/linter'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module PubSub
         | 
| 4 | 
            +
              mattr_accessor :subscriptions
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              class Subscriptions
         | 
| 7 | 
            +
                include Singleton
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                cattr_accessor :subscriptions_path
         | 
| 10 | 
            +
                self.subscriptions_path = 'config/subscriptions.yml'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def self.load!
         | 
| 13 | 
            +
                  PubSub.subscriptions = Subscriptions.instance
         | 
| 14 | 
            +
                  PubSub.subscriptions.register(:all)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def self.lint!
         | 
| 18 | 
            +
                  instance.lint!
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def lint!
         | 
| 22 | 
            +
                  Linter.new(config).lint!
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def initialize
         | 
| 26 | 
            +
                  @config = YAML.load_file(self.class.subscriptions_path)
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def register(scope = :all)
         | 
| 30 | 
            +
                  (scope == :all ? config : config.slice(scope.to_s)).each do |domain_name, subscriptions|
         | 
| 31 | 
            +
                    subscriptions.each do |event_name, subscription_type|
         | 
| 32 | 
            +
                      options = {}
         | 
| 33 | 
            +
                      options[:on] = event_name unless event_name == 'all_events'
         | 
| 34 | 
            +
                      options[:async] = true if subscription_type == 'async'
         | 
| 35 | 
            +
                      options[:broadcaster] = :run_once if subscription_type == 'run_once'
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                      Wisper.subscribe("::#{domain_name.camelize}".constantize, options)
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                def clear!
         | 
| 43 | 
            +
                  Wisper.clear
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                private
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                attr_reader :config
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
            end
         | 
| @@ -0,0 +1,12 @@ | |
| 1 | 
            +
            module PubSub
         | 
| 2 | 
            +
              module Testing
         | 
| 3 | 
            +
                module EventDataHelper
         | 
| 4 | 
            +
                  def event_data_for(event_name, **payload)
         | 
| 5 | 
            +
                    EventClassFactory.
         | 
| 6 | 
            +
                      build(event_name, abstract_event_class: payload.delete(:abstract_event_class)).
         | 
| 7 | 
            +
                      new(payload).
         | 
| 8 | 
            +
                      attributes
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
            end
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            module PubSub
         | 
| 2 | 
            +
              module Testing
         | 
| 3 | 
            +
                module SubscriptionsHelper
         | 
| 4 | 
            +
                  def with_subscription_to(*domains)
         | 
| 5 | 
            +
                    domains.each do |domain|
         | 
| 6 | 
            +
                      PubSub.subscriptions.register(domain)
         | 
| 7 | 
            +
                    end
         | 
| 8 | 
            +
                    yield
         | 
| 9 | 
            +
                    clear_wisper_subscriptions!
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def subscribe_logger!
         | 
| 13 | 
            +
                    PubSub.subscriptions.register(:logging)
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                  module_function :subscribe_logger!
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def clear_wisper_subscriptions!
         | 
| 18 | 
            +
                    PubSub.subscriptions.clear!
         | 
| 19 | 
            +
                    subscribe_logger!
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                  module_function :clear_wisper_subscriptions!
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,117 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: pubsub_on_rails
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.0.1
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Stevo
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: bin
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2019-05-06 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: dry-struct
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - ">="
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '0'
         | 
| 20 | 
            +
              type: :runtime
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - ">="
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '0'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: wisper
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: 2.0.0
         | 
| 34 | 
            +
              type: :runtime
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - "~>"
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: 2.0.0
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: wisper-sidekiq
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - ">="
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: '0'
         | 
| 48 | 
            +
              type: :runtime
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - ">="
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: '0'
         | 
| 55 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 56 | 
            +
              name: wisper-rspec
         | 
| 57 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - ">="
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: '0'
         | 
| 62 | 
            +
              type: :runtime
         | 
| 63 | 
            +
              prerelease: false
         | 
| 64 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 | 
            +
                requirements:
         | 
| 66 | 
            +
                - - ">="
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            +
                    version: '0'
         | 
| 69 | 
            +
            description: Opinionated publish-subscribe pattern for ruby and rails
         | 
| 70 | 
            +
            email:
         | 
| 71 | 
            +
            - b.kosmowski@selleo.com
         | 
| 72 | 
            +
            executables: []
         | 
| 73 | 
            +
            extensions: []
         | 
| 74 | 
            +
            extra_rdoc_files: []
         | 
| 75 | 
            +
            files:
         | 
| 76 | 
            +
            - Gemfile
         | 
| 77 | 
            +
            - Gemfile.lock
         | 
| 78 | 
            +
            - LICENSE.md
         | 
| 79 | 
            +
            - lib/pub_sub.rb
         | 
| 80 | 
            +
            - lib/pub_sub/domain.rb
         | 
| 81 | 
            +
            - lib/pub_sub/domain_event.rb
         | 
| 82 | 
            +
            - lib/pub_sub/domain_event_handler.rb
         | 
| 83 | 
            +
            - lib/pub_sub/emit.rb
         | 
| 84 | 
            +
            - lib/pub_sub/event_class_factory.rb
         | 
| 85 | 
            +
            - lib/pub_sub/event_emission.rb
         | 
| 86 | 
            +
            - lib/pub_sub/linter.rb
         | 
| 87 | 
            +
            - lib/pub_sub/payload_attribute.rb
         | 
| 88 | 
            +
            - lib/pub_sub/subscriptions.rb
         | 
| 89 | 
            +
            - lib/pub_sub/testing.rb
         | 
| 90 | 
            +
            - lib/pub_sub/testing/event_data_helper.rb
         | 
| 91 | 
            +
            - lib/pub_sub/testing/subscription_helpers.rb
         | 
| 92 | 
            +
            - lib/pub_sub/version.rb
         | 
| 93 | 
            +
            - lib/pubsub_on_rails.rb
         | 
| 94 | 
            +
            homepage: https://github.com/Selleo/pubsub_on_rails
         | 
| 95 | 
            +
            licenses:
         | 
| 96 | 
            +
            - MIT
         | 
| 97 | 
            +
            metadata: {}
         | 
| 98 | 
            +
            post_install_message: 
         | 
| 99 | 
            +
            rdoc_options: []
         | 
| 100 | 
            +
            require_paths:
         | 
| 101 | 
            +
            - lib
         | 
| 102 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 103 | 
            +
              requirements:
         | 
| 104 | 
            +
              - - ">="
         | 
| 105 | 
            +
                - !ruby/object:Gem::Version
         | 
| 106 | 
            +
                  version: '0'
         | 
| 107 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 108 | 
            +
              requirements:
         | 
| 109 | 
            +
              - - ">="
         | 
| 110 | 
            +
                - !ruby/object:Gem::Version
         | 
| 111 | 
            +
                  version: '0'
         | 
| 112 | 
            +
            requirements: []
         | 
| 113 | 
            +
            rubygems_version: 3.0.3
         | 
| 114 | 
            +
            signing_key: 
         | 
| 115 | 
            +
            specification_version: 4
         | 
| 116 | 
            +
            summary: Opinionated publish-subscribe pattern for ruby and rails
         | 
| 117 | 
            +
            test_files: []
         |