Class: ActiveWarehouse::Cube

Inherits:
Object
  • Object
show all
Defined in:
lib/active_warehouse/cube.rb

Overview

A Cube represents a collection of dimensions operating on a fact. The Cube provides a front-end for getting at the underlying data. Cubes support pluggable aggregation. The default aggregation is the NoAggregate which goes directly to the fact and dimensions to answer queries.

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.connect_throughObject

Specify the ActiveRecord class to connect through Note: this is a potential directive in a Cube subclass



152
153
154
# File 'lib/active_warehouse/cube.rb', line 152

def connect_through
  @connect_through
end

.temp_dirObject

The temp directory for storing files during warehouse rebuilds



145
146
147
# File 'lib/active_warehouse/cube.rb', line 145

def temp_dir
  @temp_dir
end

Class Method Details

.aggregateObject

Defaults to NoAggregate strategy.



163
164
165
# File 'lib/active_warehouse/cube.rb', line 163

def aggregate
  @aggregate ||= ActiveWarehouse::Aggregate::NoAggregate.new(self)
end

.aggregate_class(agg_class) ⇒ Object



167
168
169
# File 'lib/active_warehouse/cube.rb', line 167

def aggregate_class(agg_class)
  @aggregate = agg_class.new(self)
end

.aggregate_fieldsObject

returns the aggregate fields for this cube removing the aggregate fields that are defined in fact class that are related to hierarchical dimension, but the cube doesn’t pivot on any hierarchical dimensions



94
95
96
# File 'lib/active_warehouse/cube.rb', line 94

def aggregate_fields
  fact_class.aggregate_fields.reject {|field| !pivot_on_hierarchical_dimension? and !field.levels_from_parent.empty? } 
end

.class_name(name) ⇒ Object

Get the class name for the specified cube name Example: Regional Sales will become RegionalSalesCube



100
101
102
103
104
# File 'lib/active_warehouse/cube.rb', line 100

def class_name(name)
  cube_name = name.to_s
  cube_name = "#{cube_name}_cube" unless cube_name =~ /_cube$/
  cube_name.classify
end

.connectionObject

Get an adapter connection



158
159
160
# File 'lib/active_warehouse/cube.rb', line 158

def connection
  connect_through.connection
end

.dimension_class(dimension_name) ⇒ Object

Get the dimension class for the specified dimension name



124
125
126
# File 'lib/active_warehouse/cube.rb', line 124

def dimension_class(dimension_name)
  fact_class.dimension_relationships[dimension_name.to_sym].class_name.constantize      
end

.dimension_classesObject

Get a list of dimension class instances



117
118
119
120
121
# File 'lib/active_warehouse/cube.rb', line 117

def dimension_classes
  dimensions.collect do |dimension_name|
    dimension_class(dimension_name)
  end
end

.dimensionsObject

Get the dimensions that this cube pivots on



66
67
68
# File 'lib/active_warehouse/cube.rb', line 66

def dimensions
  @dimensions ||= fact_class.dimension_relationships.collect{|k,v| k}
end

.dimensions_hierarchiesObject

Get an OrderedHash of each dimension mapped to its hierarchies which will be included in the cube



72
73
74
75
76
77
78
79
80
# File 'lib/active_warehouse/cube.rb', line 72

def dimensions_hierarchies
  if @dimensions_hierarchies.nil?
    @dimensions_hierarchies = OrderedHash.new
    dimensions.each do |dimension|
      @dimensions_hierarchies[dimension] = fact_class.dimension_class(dimension).hierarchies
    end
  end
  @dimensions_hierarchies
end

.fact_classObject

Get the aggregated fact class instance



112
113
114
# File 'lib/active_warehouse/cube.rb', line 112

def fact_class
  fact_class_name.constantize
end

.fact_class_nameObject

Get the aggregated fact class name



107
108
109
# File 'lib/active_warehouse/cube.rb', line 107

def fact_class_name
  ActiveWarehouse::Fact.class_name(@fact_name || name.sub(/Cube$/,'').underscore.to_sym)
end

.inherited(subclass) ⇒ Object

Callback which is invoked when subclasses are created



11
12
13
# File 'lib/active_warehouse/cube.rb', line 11

def inherited(subclass)
  subclasses << subclass
end

.last_modifiedObject

Get the time when the fact or any dimension referenced in this cube was last modified



135
136
137
138
139
140
141
142
# File 'lib/active_warehouse/cube.rb', line 135

def last_modified
  lm = fact_class.last_modified
  dimensions.each do |dimension|
    dim = ActiveWarehouse::Dimension.class_for_name(dimension)
    lm = dim.last_modified if dim.last_modified > lm
  end
  lm
end

.loggerObject

Get the cube logger



129
130
131
# File 'lib/active_warehouse/cube.rb', line 129

def logger
  @logger ||= Logger.new('cube.log')
end

.pivot_on_hierarchical_dimension?Boolean

returns true if this cube pivots on a hierarchical dimension.

Returns:

  • (Boolean)


83
84
85
86
87
88
# File 'lib/active_warehouse/cube.rb', line 83

def pivot_on_hierarchical_dimension?
  dimension_classes.each do |dimension|
    return true if dimension.hierarchical_dimension?
  end
  return false
end

.pivots_on(*dimension_list) ⇒ Object Also known as: pivot_on

Defines the dimensions that this cube pivots on. If the fact name and cube name are different (for example, if a PurchaseCube does not report on a PurchaseFact) then you must declare the reports_on first.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/active_warehouse/cube.rb', line 24

def pivots_on(*dimension_list)
  @dimensions_hierarchies = OrderedHash.new
  @dimensions = []
  dimension_list.each do |dimension|
    case dimension
    when Symbol, String
      dimensions << dimension.to_sym
      dimensions_hierarchies[dimension.to_sym] = fact_class.dimension_class(dimension).hierarchies
    when Hash
      dimension_name = dimension.keys.first.to_sym
      dimensions << dimension_name
      dimensions_hierarchies[dimension_name] = [dimension[dimension_name]].flatten
    else
      raise ArgumentError, "Each argument to pivot_on must be a symbol, string or Hash"
    end
  end
end

.populate(options = {}) ⇒ Object

Populate the data warehouse. Delegate to aggregate.populate



61
62
63
# File 'lib/active_warehouse/cube.rb', line 61

def populate(options={})
  aggregate.populate
end

.rebuild(options = {}) ⇒ Object

Rebuild the data warehouse.



56
57
58
# File 'lib/active_warehouse/cube.rb', line 56

def rebuild(options={})
  populate(options)
end

.reports_on(fact_name) ⇒ Object Also known as: report_on

Defines the fact name, without the ‘Fact’ suffix, that this cube reports on. For instance, if you have PurchaseFact, you could then call reports_on :purchase.

The default value for reports_on is to take the name of the cube, i.e. PurchaseCube, and remove the Cube suffix. The assumption is that your Cube name matches your Fact name.



50
51
52
# File 'lib/active_warehouse/cube.rb', line 50

def reports_on(fact_name)
  @fact_name = fact_name
end

.subclassesObject

Get a list of all known subclasses



16
17
18
# File 'lib/active_warehouse/cube.rb', line 16

def subclasses
  @subclasses ||= []
end

Instance Method Details

#connectionObject

Get the database connection (delegates to Cube.connection class method)



198
199
200
# File 'lib/active_warehouse/cube.rb', line 198

def connection
  self.class.connection
end

#query(*args) ⇒ Object

Query the cube. The column dimension, column hierarchy, row dimension and row hierarchy are all required.

The conditions value is a String that represents a SQL condition appended to the where clause. TODO: this may eventually be converted to another query language.

The cstage value represents the current column drill down stage and defaults to 0.

The rstage value represents the current row drill down stage and defaults to 0. Filters contains key/value pairs where the key is a string of ‘dimension.column’ and the value is the value to filter by. For example:

filters = => 2007, ‘product.category’ => ‘Food’ query(:date, :cy, :store, :region, 1, 0, filters)

Note that product.category refers to a dimension which is not actually visible but which is both part of the cube and is used for filtering.



193
194
195
# File 'lib/active_warehouse/cube.rb', line 193

def query(*args)
  self.class.aggregate.query(*args)
end