class Axiom::Relation::Header
A set of attributes that correspond to values in each tuple
Constants
- EMPTY
Represent an empty set of attributes
Attributes
The header keys
@return [Keys]
@api private
Public Class Methods
Coerce an Array-like object into a Header
@param [Header, to_ary
] object
the header or attributes
@param [Hash] options
@yield [attribute]
@yieldparam [Attribute, Array] attribute
@return [Header]
@api private
# File lib/axiom/relation/header.rb, line 49 def self.coerce(object, options = EMPTY_HASH) if object.kind_of?(self) object else # Find the attribute with the block if possible, then fallback # to the default coercion method. block = lambda do |attribute| coerce_attribute(block_given? && yield(attribute) || attribute) end new(Array(object).map(&block), options) end end
Instantiate a Header
@example
header = Header.new(attributes)
@param [Array<Attribute>] attributes
optional attributes
@param [Hash] _options
@return [Header]
@api public
# File lib/axiom/relation/header.rb, line 74 def self.new(attributes = EMPTY_ARRAY, *) assert_unique_names(attributes.map(&:name)) super end
Initialize a Header
@example
header = Header.new(attributes, keys: [[:id]])
@param [Array] attributes
@param [Hash] options
@return [undefined]
@api public
# File lib/axiom/relation/header.rb, line 136 def initialize(attributes, options = EMPTY_HASH) @to_ary = self.class.freezer.call(attributes) @attribute_for = Hash[@to_ary.map(&:name).zip(@to_ary)] @keys = coerce_keys(options.fetch(:keys, EMPTY_ARRAY)) end
Private Class Methods
Assert the names are unique
@param [Array<Symbol>] names
@return [undefined]
@raise [DuplicateNameError]
raised if the names are not unique
@api private
# File lib/axiom/relation/header.rb, line 100 def self.assert_unique_names(names) duplicates = duplicate_names(names) if duplicates fail DuplicateNameError, "duplicate names: #{duplicates}" end end
Coerce the attribute into an Attribute
@param [Object] attribute
@return [Attribute]
@api private
# File lib/axiom/relation/header.rb, line 86 def self.coerce_attribute(attribute) Attribute.coerce(attribute) end
Returns the duplicate names, if any
@param [Array<Symbol>] names
@return [Array<Symbol>]
returns an array of duplicate names
@return [nil]
returns nil if there are no duplicate names
@api private
# File lib/axiom/relation/header.rb, line 118 def self.duplicate_names(names) names.select { |name| names.count(name) > 1 }.uniq! end
Public Instance Methods
Evaluate a block within the context of the header
@yield [context]
@yieldparam [Evaluator::Context] context
@yieldreturn [Evaluator::Context]
@return [Header]
@api private
# File lib/axiom/relation/header.rb, line 303 def context(&block) Evaluator::Context.new(self, &block) end
Return the difference of the header with another header
The original keys from the header are reused because a difference does not affect key constraints.
@example
difference = header.difference(other)
@param [Header] other
@return [Header]
@api public
# File lib/axiom/relation/header.rb, line 287 def difference(other) other = coerce(other) new(to_ary - other, keys: keys - other.keys) end
Iterate over each attribute in the header
@example
header = Header.new(attributes) header.each { |attribute| ... }
@yield [attribute]
@yieldparam [Attribute] attribute
each attribute in the header
@return [self]
@api public
# File lib/axiom/relation/header.rb, line 156 def each return to_enum unless block_given? to_ary.each { |attribute| yield attribute } self end
Test if there are no attributes
@example
header.empty? # => true or false
@return [Boolean]
@api public
# File lib/axiom/relation/header.rb, line 324 def empty? to_ary.empty? end
Return a header with the new attributes added
The original keys from the header are reused because an extension does not affect key constraints.
@example
extended = header.extend(attributes)
@param [#to_ary] attributes
the attributes to add to the header
@return [Header]
@api public
# File lib/axiom/relation/header.rb, line 214 def extend(attributes) new(to_ary + coerce(attributes), keys: keys) end
Lookup an attribute in the header given a name
@example
attribute = header.call(:id)
@param [Attribute, to_ary
, to_sym] name
@return [Attribute]
the attribute when the name is known
@api public
# File lib/axiom/relation/header.rb, line 173 def fetch(name) @attribute_for.fetch(Attribute.name_from(name)) do |attribute_name| fail( UnknownAttributeError, "the attribute #{attribute_name} is unknown" ) end end
Return the intersection of the header with another header
The unique keys from the headers become the new keys because an intersection strengthens key constraints.
@example
intersection = header.intersect(other)
@param [Header] other
@return [Header]
@api public
# File lib/axiom/relation/header.rb, line 250 def intersect(other) other = coerce(other) attributes = to_ary & other new(attributes, keys: (keys | other.keys).project(attributes)) end
Return a header with only the attributes specified
The unique keys intersected with the attributes become the new keys because a projection strengthens key constraints.
@example
projected = header.project(attributes)
@param [#map] attributes
the attributes to keep in the header
@return [Header]
@api public
# File lib/axiom/relation/header.rb, line 196 def project(attributes) coerce(attributes, keys: keys.project(attributes)) end
Return a header with the attributes renamed
The attributes in the original keys are renamed, but a rename does not otherwise affect the key constraints.
@example
renamed = header.rename(aliases)
@param [Aliases] aliases
the old and new attribute names
@return [Header]
@api public
# File lib/axiom/relation/header.rb, line 232 def rename(aliases) aliases = Algebra::Rename::Aliases.coerce(self, aliases) new(map(&aliases.method(:[])), keys: keys.rename(aliases)) end
The number of attributes
@return [Integer]
@api public
# File lib/axiom/relation/header.rb, line 312 def size to_ary.size end
Return the union of the header with another header
The common keys from the headers become the new keys because a union weakens key constraints.
@example
union = header.union(other)
@param [Header] other
@return [Header]
@api public
# File lib/axiom/relation/header.rb, line 269 def union(other) other = coerce(other) new(to_ary | other, keys: keys & other.keys) end
Private Instance Methods
Coerce the object into a Header
@param [Array] args
@return [Header]
@api private
# File lib/axiom/relation/header.rb, line 359 def coerce(*args) self.class.coerce(*args, &@attribute_for.method(:[])) end
Coerce the keys into an Array of Headers
@return [Array]
@return [Array<Header>]
@api private
# File lib/axiom/relation/header.rb, line 348 def coerce_keys(keys) Keys.coerce(keys) { |attributes| coerce(attributes) } end
Utility method to instantiate a Header
@param [Array] args
@return [Header]
@api private
# File lib/axiom/relation/header.rb, line 337 def new(*args) self.class.new(*args) end