Freshly/spicerack

View on GitHub
collectible/lib/collectible/collection/maintain_sort_order.rb

Summary

Maintainability
A
1 hr
Test Coverage
A
96%
# frozen_string_literal: true

module Collectible
  module Collection
    module MaintainSortOrder
      extend ActiveSupport::Concern

      included do
        delegate :maintain_sort_order?, to: :class

        disallow_when_sorted :insert, :unshift, :prepend
        maintain_sorted_order_after :initialize, :push, :<<, :concat
      end

      class_methods do
        def inherited(base)
          base.maintain_sort_order if maintain_sort_order?
          super
        end

        def maintain_sort_order?
          @maintain_sort_order.present?
        end

        protected

        def maintain_sort_order
          @maintain_sort_order = true
        end

        private

        def maintain_sorted_order_after(*methods)
          methods.each do |method_name|
            around_method(method_name, prevent_double_wrapping_for: "MaintainSortingOrder") do |*items|
              super(*items).tap do
                sort! if maintain_sort_order?
              end
            end
          end
        end

        def disallow_when_sorted(*methods)
          methods.each do |method_name|
            around_method(method_name, prevent_double_wrapping_for: "MaintainSortingOrder") do |*args, **opts, &block|
              raise Collectible::MethodNotAllowedError, "cannot call #{method_name} when sorted" if maintain_sort_order?

              # TODO: replace with `super(...)` when <= 2.6 support is dropped
              if RUBY_VERSION < "2.7" && opts.blank?
                super(*args, &block)
              else
                super(*args, **opts, &block)
              end
            end
          end
        end
      end
    end
  end
end