lib/axiom/algebra/product.rb

Summary

Maintainability
A
0 mins
Test Coverage
# encoding: utf-8

module Axiom
  module Algebra

    # The cartesian product between relations
    class Product < Relation
      include Relation::Operation::Combination

      # Instantiate a new Product
      #
      # @example
      #   product = Product.new(left, right)
      #
      # @param [Relation] left
      # @param [Relation] right
      #
      # @return [Join]
      #
      # @api public
      def self.new(left, right)
        assert_disjointed_headers(left, right)
        super
      end

      # Assert the headers do not have common attributes
      #
      # @param [Relation] left
      # @param [Relation] right
      #
      # @return [undefined]
      #
      # @raise [InvalidHeaderError]
      #   raised if there are common attributes between the headers
      #
      # @api private
      def self.assert_disjointed_headers(left, right)
        if (left.header & right.header).any?
          fail InvalidHeaderError, 'the headers must be disjointed'
        end
      end

      private_class_method :assert_disjointed_headers

      # Iterate over each tuple in the set
      #
      # @example
      #   product = Product.new(left, right)
      #   product.each { |tuple| ... }
      #
      # @yield [tuple]
      #
      # @yieldparam [Tuple] tuple
      #   each tuple in the set
      #
      # @return [self]
      #
      # @api public
      def each(&block)
        return to_enum unless block_given?
        util = Relation::Operation::Combination
        left.each do |left_tuple|
          util.combine_tuples(header, left_tuple, right, &block)
        end
        self
      end

      # Raise an exception when inserting into the Product
      #
      # @example
      #   product.insert(other)  # => ImmutableRelationError raised
      #
      # @return [undefined]
      #
      # @raise [ImmutableRelationError]
      #   raised when inserting into the product
      #
      # @api public
      def insert(*)
        fail ImmutableRelationError, 'inserting into a product is impossible'
      end

      # Raise an exception when deleting from the Product
      #
      # @example
      #   product.delete(other)  # => ImmutableRelationError raised
      #
      # @return [undefined]
      #
      # @raise [ImmutableRelationError]
      #   raised when deleting from the product
      #
      # @api public
      def delete(*)
        fail ImmutableRelationError, 'deleting from a product is impossible'
      end

      module Methods
        extend Aliasable

        inheritable_alias(:* => :product)

        # Return a relation that is the cartesian product of two relations
        #
        # @example
        #   product = relation.product(other)
        #
        # @param [Relation] other
        #   the other relation to find the product with
        #
        # @return [Product]
        #
        # @api public
        def product(other)
          Product.new(self, other)
        end

      end # module Methods

      Relation.class_eval { include Methods }

    end # class Product
  end # module Algebra
end # module Axiom