api/app/models/concerns/spree/webhooks/has_webhooks.rb

Summary

Maintainability
A
1 hr
Test Coverage
module Spree
  module Webhooks
    module HasWebhooks
      extend ActiveSupport::Concern

      included do
        after_create_commit(proc { queue_webhooks_requests!(inferred_event_name(:create)) })
        after_destroy_commit(proc { queue_webhooks_requests!(inferred_event_name(:delete)) })
        after_update_commit(proc { queue_webhooks_requests!(inferred_event_name(:update)) })

        def queue_webhooks_requests!(event_name)
          return if disable_spree_webhooks?
          return if Spree::Webhooks::Subscriber.none?
          return if Spree::Webhooks::Subscriber.active.with_urls_for(event_name).none?
          return if update_event?(event_name) && updating_only_ignored_attributes?
          return if webhook_payload_body.blank?

          Spree::Webhooks::Subscribers::QueueRequests.call(
            event_name: event_name, webhook_payload_body: webhook_payload_body, **webhooks_request_options
          )
        end

        def self.default_webhook_events
          model_name = name.demodulize.tableize.singularize
          %W[#{model_name}.create #{model_name}.delete #{model_name}.update]
        end

        def self.supported_webhook_events
          events = default_webhook_events
          events += custom_webhook_events if respond_to?(:custom_webhook_events)
          events
        end
      end

      private

      def webhook_payload_body
        resource_serializer.new(self, include: included_relationships).serializable_hash.to_json
      end

      def inferred_event_name(operation)
        "#{self.class.name.demodulize.tableize.singularize}.#{operation}"
      end

      def included_relationships
        if resource_serializer.relationships_to_serialize
          resource_serializer.relationships_to_serialize.keys
        else
          []
        end
      end

      def resource_serializer
        @resource_serializer ||=
          begin
            demodulized_class_name = self.class.to_s.demodulize
            "Spree::Api::V2::Platform::#{demodulized_class_name}Serializer".constantize
          end
      end

      def updating_only_ignored_attributes?
        (saved_changes.keys - ignored_attributes).empty?
      end

      def ignored_attributes
        timestamps = %w[created_at updated_at deleted_at]
        return timestamps unless self.class.respond_to?(:ignored_attributes_for_update_webhook_event)

        timestamps + self.class.ignored_attributes_for_update_webhook_event
      end

      def update_event?(event_name)
        event_name.end_with?('.update')
      end

      def disable_spree_webhooks?
        ENV['DISABLE_SPREE_WEBHOOKS'] == 'true'
      end

      def webhooks_request_options
        {}
      end
    end
  end
end