Class: Axiom::Relation::Header

Inherits:
Object
  • Object
show all
Extended by:
Aliasable
Includes:
Enumerable
Defined in:
lib/axiom/relation/header.rb

Overview

A set of attributes that correspond to values in each tuple

Direct Known Subclasses

Operation::Sorted::DirectionSet

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Aliasable

inheritable_alias

Constructor Details

#initialize(attributes, options = EMPTY_HASH) ⇒ undefined

Initialize a Header

Examples:

header = Header.new(attributes, keys: [[:id]])

Parameters:

  • attributes (Array)
  • options (Hash) (defaults to: EMPTY_HASH)


136
137
138
139
140
# 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

Instance Attribute Details

#keysKeys (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The header keys

Returns:



24
25
26
# File 'lib/axiom/relation/header.rb', line 24

def keys
  @keys
end

#to_aryArray (readonly)

Convert the Header into an Array

Examples:

array = header.to_ary

Returns:

  • (Array)


34
35
36
# File 'lib/axiom/relation/header.rb', line 34

def to_ary
  @to_ary
end

Class Method Details

.coerce(object, options = EMPTY_HASH) {|attribute| ... } ⇒ Header

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Coerce an Array-like object into a Header

Parameters:

  • object (Header, #to_ary)

    the header or attributes

  • options (Hash) (defaults to: EMPTY_HASH)

Yields:

  • (attribute)

Yield Parameters:

Returns:



49
50
51
52
53
54
55
56
57
58
59
60
# 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

.new(attributes = EMPTY_ARRAY) ⇒ Header

Instantiate a Header

Examples:

header = Header.new(attributes)

Parameters:

  • attributes (Array<Attribute>) (defaults to: EMPTY_ARRAY)

    optional attributes

  • _options (Hash)

Returns:



74
75
76
77
# File 'lib/axiom/relation/header.rb', line 74

def self.new(attributes = EMPTY_ARRAY, *)
  assert_unique_names(attributes.map(&:name))
  super
end

Instance Method Details

#context {|context| ... } ⇒ Header

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Evaluate a block within the context of the header

Yields:

Yield Parameters:

Yield Returns:

Returns:



303
304
305
# File 'lib/axiom/relation/header.rb', line 303

def context(&block)
  Evaluator::Context.new(self, &block)
end

#difference(other) ⇒ Header

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.

Examples:

difference = header.difference(other)

Parameters:

Returns:



287
288
289
290
# File 'lib/axiom/relation/header.rb', line 287

def difference(other)
  other = coerce(other)
  new(to_ary - other, keys: keys - other.keys)
end

#each {|attribute| ... } ⇒ self

Iterate over each attribute in the header

Examples:

header = Header.new(attributes)
header.each { |attribute| ... }

Yields:

  • (attribute)

Yield Parameters:

  • attribute (Attribute)

    each attribute in the header

Returns:

  • (self)


156
157
158
159
160
# File 'lib/axiom/relation/header.rb', line 156

def each
  return to_enum unless block_given?
  to_ary.each { |attribute| yield attribute }
  self
end

#empty?Boolean

Test if there are no attributes

Examples:

header.empty?  # => true or false

Returns:

  • (Boolean)


324
325
326
# File 'lib/axiom/relation/header.rb', line 324

def empty?
  to_ary.empty?
end

#extend(attributes) ⇒ Header

Return a header with the new attributes added

The original keys from the header are reused because an extension does not affect key constraints.

Examples:

extended = header.extend(attributes)

Parameters:

  • attributes (#to_ary)

    the attributes to add to the header

Returns:



214
215
216
# File 'lib/axiom/relation/header.rb', line 214

def extend(attributes)
  new(to_ary + coerce(attributes), keys: keys)
end

#fetch(name) ⇒ Attribute

Lookup an attribute in the header given a name

Examples:

attribute = header.call(:id)

Parameters:

Returns:

  • (Attribute)

    the attribute when the name is known



173
174
175
176
177
178
179
180
# 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

#intersect(other) ⇒ Header

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.

Examples:

intersection = header.intersect(other)

Parameters:

Returns:



250
251
252
253
254
# 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

#project(attributes) ⇒ Header

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.

Examples:

projected = header.project(attributes)

Parameters:

  • attributes (#map)

    the attributes to keep in the header

Returns:



196
197
198
# File 'lib/axiom/relation/header.rb', line 196

def project(attributes)
  coerce(attributes, keys: keys.project(attributes))
end

#rename(aliases) ⇒ Header

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.

Examples:

renamed = header.rename(aliases)

Parameters:

  • aliases (Aliases)

    the old and new attribute names

Returns:



232
233
234
235
# 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

#sizeInteger

The number of attributes

Returns:

  • (Integer)


312
313
314
# File 'lib/axiom/relation/header.rb', line 312

def size
  to_ary.size
end

#union(other) ⇒ Header

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.

Examples:

union = header.union(other)

Parameters:

Returns:



269
270
271
272
# File 'lib/axiom/relation/header.rb', line 269

def union(other)
  other = coerce(other)
  new(to_ary | other, keys: keys & other.keys)
end