mainej-activewarehouse 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/activewarehouse/README +99 -0
- data/activewarehouse/Rakefile +165 -0
- data/activewarehouse/TODO +4 -0
- data/activewarehouse/db/migrations/001_create_table_reports.rb +28 -0
- data/activewarehouse/doc/references.txt +4 -0
- data/activewarehouse/generators/bridge/USAGE +1 -0
- data/activewarehouse/generators/bridge/bridge_generator.rb +46 -0
- data/activewarehouse/generators/bridge/templates/fixture.yml +5 -0
- data/activewarehouse/generators/bridge/templates/migration.rb +27 -0
- data/activewarehouse/generators/bridge/templates/model.rb +3 -0
- data/activewarehouse/generators/bridge/templates/unit_test.rb +8 -0
- data/activewarehouse/generators/cube/USAGE +1 -0
- data/activewarehouse/generators/cube/cube_generator.rb +28 -0
- data/activewarehouse/generators/cube/templates/model.rb +3 -0
- data/activewarehouse/generators/cube/templates/unit_test.rb +8 -0
- data/activewarehouse/generators/date_dimension/USAGE +1 -0
- data/activewarehouse/generators/date_dimension/date_dimension_generator.rb +16 -0
- data/activewarehouse/generators/date_dimension/templates/fixture.yml +5 -0
- data/activewarehouse/generators/date_dimension/templates/migration.rb +31 -0
- data/activewarehouse/generators/date_dimension/templates/model.rb +3 -0
- data/activewarehouse/generators/date_dimension/templates/unit_test.rb +8 -0
- data/activewarehouse/generators/dimension/USAGE +1 -0
- data/activewarehouse/generators/dimension/dimension_generator.rb +46 -0
- data/activewarehouse/generators/dimension/templates/fixture.yml +5 -0
- data/activewarehouse/generators/dimension/templates/migration.rb +11 -0
- data/activewarehouse/generators/dimension/templates/model.rb +3 -0
- data/activewarehouse/generators/dimension/templates/unit_test.rb +8 -0
- data/activewarehouse/generators/dimension_view/USAGE +1 -0
- data/activewarehouse/generators/dimension_view/dimension_view_generator.rb +62 -0
- data/activewarehouse/generators/dimension_view/templates/migration.rb +17 -0
- data/activewarehouse/generators/dimension_view/templates/model.rb +3 -0
- data/activewarehouse/generators/dimension_view/templates/unit_test.rb +10 -0
- data/activewarehouse/generators/fact/USAGE +1 -0
- data/activewarehouse/generators/fact/fact_generator.rb +46 -0
- data/activewarehouse/generators/fact/templates/fixture.yml +5 -0
- data/activewarehouse/generators/fact/templates/migration.rb +13 -0
- data/activewarehouse/generators/fact/templates/model.rb +3 -0
- data/activewarehouse/generators/fact/templates/unit_test.rb +10 -0
- data/activewarehouse/generators/time_dimension/USAGE +1 -0
- data/activewarehouse/generators/time_dimension/templates/fixture.yml +5 -0
- data/activewarehouse/generators/time_dimension/templates/migration.rb +12 -0
- data/activewarehouse/generators/time_dimension/templates/model.rb +3 -0
- data/activewarehouse/generators/time_dimension/templates/unit_test.rb +8 -0
- data/activewarehouse/generators/time_dimension/time_dimension_generator.rb +14 -0
- data/activewarehouse/init.rb +1 -0
- data/activewarehouse/install.rb +5 -0
- data/activewarehouse/lib/active_warehouse.rb +91 -0
- data/activewarehouse/lib/active_warehouse/aggregate.rb +75 -0
- data/activewarehouse/lib/active_warehouse/aggregate/dwarf_aggregate.rb +369 -0
- data/activewarehouse/lib/active_warehouse/aggregate/dwarf_common.rb +44 -0
- data/activewarehouse/lib/active_warehouse/aggregate/dwarf_printer.rb +34 -0
- data/activewarehouse/lib/active_warehouse/aggregate/no_aggregate.rb +212 -0
- data/activewarehouse/lib/active_warehouse/aggregate/pid_aggregate.rb +29 -0
- data/activewarehouse/lib/active_warehouse/aggregate_field.rb +59 -0
- data/activewarehouse/lib/active_warehouse/bridge.rb +19 -0
- data/activewarehouse/lib/active_warehouse/bridge/hierarchy_bridge.rb +46 -0
- data/activewarehouse/lib/active_warehouse/builder.rb +3 -0
- data/activewarehouse/lib/active_warehouse/builder/date_dimension_builder.rb +91 -0
- data/activewarehouse/lib/active_warehouse/builder/generator/generator.rb +13 -0
- data/activewarehouse/lib/active_warehouse/builder/generator/name_generator.rb +20 -0
- data/activewarehouse/lib/active_warehouse/builder/generator/paragraph_generator.rb +11 -0
- data/activewarehouse/lib/active_warehouse/builder/random_data_builder.rb +239 -0
- data/activewarehouse/lib/active_warehouse/builder/test_data_builder.rb +54 -0
- data/activewarehouse/lib/active_warehouse/calculated_field.rb +27 -0
- data/activewarehouse/lib/active_warehouse/compat/compat.rb +49 -0
- data/activewarehouse/lib/active_warehouse/core_ext.rb +1 -0
- data/activewarehouse/lib/active_warehouse/core_ext/time.rb +5 -0
- data/activewarehouse/lib/active_warehouse/core_ext/time/calculations.rb +40 -0
- data/activewarehouse/lib/active_warehouse/cube.rb +235 -0
- data/activewarehouse/lib/active_warehouse/cube_query_result.rb +69 -0
- data/activewarehouse/lib/active_warehouse/dimension.rb +329 -0
- data/activewarehouse/lib/active_warehouse/dimension/date_dimension.rb +15 -0
- data/activewarehouse/lib/active_warehouse/dimension/dimension_reflection.rb +21 -0
- data/activewarehouse/lib/active_warehouse/dimension/dimension_view.rb +27 -0
- data/activewarehouse/lib/active_warehouse/dimension/hierarchical_dimension.rb +99 -0
- data/activewarehouse/lib/active_warehouse/dimension/slowly_changing_dimension.rb +147 -0
- data/activewarehouse/lib/active_warehouse/fact.rb +239 -0
- data/activewarehouse/lib/active_warehouse/field.rb +74 -0
- data/activewarehouse/lib/active_warehouse/migrations.rb +64 -0
- data/activewarehouse/lib/active_warehouse/ordered_hash.rb +34 -0
- data/activewarehouse/lib/active_warehouse/prejoin_fact.rb +97 -0
- data/activewarehouse/lib/active_warehouse/report.rb +7 -0
- data/activewarehouse/lib/active_warehouse/report/abstract_report.rb +149 -0
- data/activewarehouse/lib/active_warehouse/report/chart_report.rb +9 -0
- data/activewarehouse/lib/active_warehouse/report/data_cell.rb +21 -0
- data/activewarehouse/lib/active_warehouse/report/data_column.rb +19 -0
- data/activewarehouse/lib/active_warehouse/report/data_row.rb +15 -0
- data/activewarehouse/lib/active_warehouse/report/dimension.rb +58 -0
- data/activewarehouse/lib/active_warehouse/report/table_report.rb +38 -0
- data/activewarehouse/lib/active_warehouse/version.rb +9 -0
- data/activewarehouse/lib/active_warehouse/view.rb +9 -0
- data/activewarehouse/lib/active_warehouse/view/crumb.rb +64 -0
- data/activewarehouse/lib/active_warehouse/view/report_helper.rb +98 -0
- data/activewarehouse/lib/active_warehouse/view/table_view.rb +134 -0
- data/activewarehouse/lib/active_warehouse/view/yui_adapter.rb +68 -0
- data/activewarehouse/tasks/active_warehouse_tasks.rake +122 -0
- metadata +237 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
module ActiveWarehouse #:nodoc:
|
2
|
+
# Encapsulates a field.
|
3
|
+
class Field
|
4
|
+
# The owning class which is either a Fact or Dimension
|
5
|
+
attr_reader :owning_class
|
6
|
+
|
7
|
+
# The field name
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
# The field type
|
11
|
+
attr_reader :type
|
12
|
+
|
13
|
+
attr_accessor :limit
|
14
|
+
attr_accessor :scale
|
15
|
+
attr_accessor :precision
|
16
|
+
|
17
|
+
# A Hash of options for the field
|
18
|
+
attr_reader :field_options
|
19
|
+
|
20
|
+
# +owning_class+ is the class of the table, either Fact or Dimension, that
|
21
|
+
# this field is found in. Must somehow subclass ActiveRecord::Base
|
22
|
+
# +name+ is the name of this field.
|
23
|
+
# +field_options+ is a hash of raw options from the original definition.
|
24
|
+
# Options can include :label => a column alias or label for this field,
|
25
|
+
# :table_alias for a table alias (useful for building queries)
|
26
|
+
def initialize(owning_class, name, type, field_options = {})
|
27
|
+
@owning_class = owning_class
|
28
|
+
@name = name
|
29
|
+
@type = type
|
30
|
+
@field_options = field_options
|
31
|
+
@label = field_options[:label]
|
32
|
+
@table_alias = field_options[:table_alias]
|
33
|
+
end
|
34
|
+
|
35
|
+
# returns the :label set in field_options, or from_table_name+'_'+name.
|
36
|
+
# Unless you have table_alias specified, then label will return table_alias+'_'+name.
|
37
|
+
# The default label can exceed database limits, so use :label to override.
|
38
|
+
def label
|
39
|
+
@label ? @label : "#{table_alias || from_table_name}_#{name}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# returns name of this field, matches name of the column
|
43
|
+
def name
|
44
|
+
@name
|
45
|
+
end
|
46
|
+
|
47
|
+
# returns rails specific column type, e.g. :float or :string
|
48
|
+
def column_type
|
49
|
+
@type
|
50
|
+
end
|
51
|
+
|
52
|
+
# convert the label into something we can use in a table.
|
53
|
+
# i.e., 'Sum of Transactions' becomes 'sum_of_transactions'
|
54
|
+
def label_for_table
|
55
|
+
label.gsub(/ /, '_').downcase
|
56
|
+
end
|
57
|
+
|
58
|
+
# returns the table name that has this fact column
|
59
|
+
def from_table_name
|
60
|
+
owning_class.table_name
|
61
|
+
end
|
62
|
+
|
63
|
+
# returns a table alias or if none set just the table name
|
64
|
+
def table_alias
|
65
|
+
@table_alias || from_table_name
|
66
|
+
end
|
67
|
+
|
68
|
+
# Get a display string for the field. Delegates to label.
|
69
|
+
def to_s
|
70
|
+
label
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module ActiveWarehouse #:nodoc:
|
2
|
+
# Responsible for migrating ActiveWarehouse tables which are automatically created.
|
3
|
+
class Migrator < ActiveRecord::Migrator
|
4
|
+
class << self
|
5
|
+
def schema_info_table_name #:nodoc:
|
6
|
+
ActiveRecord::Base.table_name_prefix + 'activewarehouse_schema_info' + ActiveRecord::Base.table_name_suffix
|
7
|
+
end
|
8
|
+
|
9
|
+
def current_version #:nodoc:
|
10
|
+
result = ActiveRecord::Base.connection.select_one("SELECT version FROM #{schema_info_table_name}")
|
11
|
+
if result
|
12
|
+
result['version'].to_i
|
13
|
+
else
|
14
|
+
# There probably isn't an entry for this plugin in the migration info table.
|
15
|
+
# We need to create that entry, and set the version to 0
|
16
|
+
ActiveRecord::Base.connection.execute("INSERT INTO #{schema_info_table_name} (version) VALUES (0)")
|
17
|
+
0
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_schema_version(version)
|
23
|
+
ActiveRecord::Base.connection.update("UPDATE #{self.class.schema_info_table_name} SET version = #{down? ? version.to_i - 1 : version.to_i}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module ActiveRecord #:nodoc:
|
29
|
+
module ConnectionAdapters #:nodoc:
|
30
|
+
module SchemaStatements #:nodoc:
|
31
|
+
def initialize_schema_information_with_activewarehouse
|
32
|
+
initialize_schema_information_without_activewarehouse
|
33
|
+
|
34
|
+
begin
|
35
|
+
execute "CREATE TABLE #{ActiveWarehouse::Migrator.schema_info_table_name} (version #{type_to_sql(:integer)})"
|
36
|
+
rescue ActiveRecord::StatementInvalid
|
37
|
+
# Schema has been initialized
|
38
|
+
end
|
39
|
+
end
|
40
|
+
alias_method_chain :initialize_schema_information, :activewarehouse
|
41
|
+
|
42
|
+
def dump_schema_information_with_activewarehouse
|
43
|
+
schema_information = []
|
44
|
+
|
45
|
+
dump = dump_schema_information_without_activewarehouse
|
46
|
+
schema_information << dump if dump
|
47
|
+
|
48
|
+
begin
|
49
|
+
plugins = ActiveRecord::Base.connection.select_all("SELECT * FROM #{ActiveWarehouse::Migrator.schema_info_table_name}")
|
50
|
+
plugins.each do |plugin|
|
51
|
+
if (version = plugin['version'].to_i) > 0
|
52
|
+
schema_information << "INSERT INTO #{ActiveWarehouse::Migrator.schema_info_table_name} (version) VALUES (#{version})"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
rescue ActiveRecord::StatementInvalid
|
56
|
+
# No Schema Info
|
57
|
+
end
|
58
|
+
|
59
|
+
schema_information.join("\n")
|
60
|
+
end
|
61
|
+
alias_method_chain :dump_schema_information, :activewarehouse
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ActiveWarehouse
|
2
|
+
# Simple ordered hash implementation
|
3
|
+
class OrderedHash < Hash
|
4
|
+
alias_method :store, :[]=
|
5
|
+
alias_method :each_pair, :each
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@keys = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def []=(key, val)
|
12
|
+
@keys << key
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def delete(key)
|
17
|
+
@keys.delete(key)
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def each
|
22
|
+
@keys.each { |k| yield k, self[k] }
|
23
|
+
end
|
24
|
+
|
25
|
+
def each_key
|
26
|
+
@keys.each { |k| yield k }
|
27
|
+
end
|
28
|
+
|
29
|
+
def each_value
|
30
|
+
@keys.each { |k| yield self[k] }
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module ActiveWarehouse #:nodoc:
|
2
|
+
# Class that supports prejoining a fact table with dimensions. This is useful if you need
|
3
|
+
# to list facts along with some or all of their detail information.
|
4
|
+
class PrejoinFact
|
5
|
+
# The fact class that this engine instance is connected to
|
6
|
+
attr_accessor :fact_class
|
7
|
+
|
8
|
+
delegate :prejoined_table_name,
|
9
|
+
:connection,
|
10
|
+
:prejoined_fields,
|
11
|
+
:dimension_relationships,
|
12
|
+
:dimension_class,
|
13
|
+
:table_name,
|
14
|
+
:columns, :to => :fact_class
|
15
|
+
|
16
|
+
# Initialize the engine instance
|
17
|
+
def initialize(fact_class)
|
18
|
+
@fact_class = fact_class
|
19
|
+
end
|
20
|
+
|
21
|
+
# Populate the prejoined fact table.
|
22
|
+
def populate(options={})
|
23
|
+
populate_prejoined_fact_table(options)
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
# Drop the storage table
|
28
|
+
def drop_prejoin_fact_table
|
29
|
+
connection.drop_table(prejoined_table_name) if connection.tables.include?(prejoined_table_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get foreign key names that are excluded.
|
33
|
+
def excluded_foreign_key_names
|
34
|
+
excluded_dimension_relations = prejoined_fields.keys.collect {|k| dimension_relationships[k]}
|
35
|
+
excluded_dimension_relations.collect {|r| r.primary_key_name}
|
36
|
+
end
|
37
|
+
|
38
|
+
# Construct the prejoined fact table.
|
39
|
+
def create_prejoined_fact_table(options={})
|
40
|
+
connection.transaction {
|
41
|
+
drop_prejoin_fact_table
|
42
|
+
|
43
|
+
connection.create_table(prejoined_table_name, :id => false) do |t|
|
44
|
+
# get all columns except the foreign_key columns for prejoined dimensions
|
45
|
+
columns.each do |c|
|
46
|
+
t.column(c.name, c.type) unless excluded_foreign_key_names.include?(c.name)
|
47
|
+
end
|
48
|
+
#prejoined_columns
|
49
|
+
prejoined_fields.each_pair do |key, value|
|
50
|
+
dclass = dimension_class(key)
|
51
|
+
dclass.columns.each do |c|
|
52
|
+
t.column(c.name, c.type) if value.include?(c.name.to_sym)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
# Populate the prejoined fact table.
|
60
|
+
def populate_prejoined_fact_table(options={})
|
61
|
+
fact_columns_string = columns.collect {|c|
|
62
|
+
"#{table_name}." + c.name unless excluded_foreign_key_names.include?(c.name)
|
63
|
+
}.compact.join(",\n")
|
64
|
+
|
65
|
+
prejoined_columns = []
|
66
|
+
|
67
|
+
tables_and_joins = "#{table_name}"
|
68
|
+
|
69
|
+
prejoined_fields.each_pair do |key, value|
|
70
|
+
dimension = dimension_class(key)
|
71
|
+
tables_and_joins += "\nJOIN #{dimension.table_name} as #{key}"
|
72
|
+
tables_and_joins += "\n ON #{table_name}.#{dimension_relationships[key].primary_key_name} = "
|
73
|
+
tables_and_joins += "#{key}.#{dimension.primary_key}"
|
74
|
+
prejoined_columns << value.collect {|v| "#{key}." + v.to_s}
|
75
|
+
end
|
76
|
+
|
77
|
+
if connection.support_select_into_table?
|
78
|
+
drop_prejoin_fact_table
|
79
|
+
sql = <<-SQL
|
80
|
+
SELECT #{fact_columns_string},
|
81
|
+
#{prejoined_columns.join(",\n")}
|
82
|
+
FROM #{tables_and_joins}
|
83
|
+
SQL
|
84
|
+
sql = connection.add_select_into_table(prejoined_table_name, sql)
|
85
|
+
else
|
86
|
+
create_prejoined_fact_table(options)
|
87
|
+
sql = <<-SQL
|
88
|
+
INSERT INTO #{prejoined_table_name}
|
89
|
+
SELECT #{fact_columns_string},
|
90
|
+
#{prejoined_columns.join(",\n")}
|
91
|
+
FROM #{tables_and_joins}
|
92
|
+
SQL
|
93
|
+
end
|
94
|
+
connection.transaction { connection.execute(sql) }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'active_warehouse/report/abstract_report'
|
2
|
+
require 'active_warehouse/report/table_report'
|
3
|
+
require 'active_warehouse/report/chart_report'
|
4
|
+
require 'active_warehouse/report/dimension'
|
5
|
+
require 'active_warehouse/report/data_column'
|
6
|
+
require 'active_warehouse/report/data_row'
|
7
|
+
require 'active_warehouse/report/data_cell'
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module ActiveWarehouse #:nodoc:
|
2
|
+
module Report #:nodoc:
|
3
|
+
# Base module for reports.
|
4
|
+
module AbstractReport
|
5
|
+
|
6
|
+
# Array of parameters which will be passed
|
7
|
+
attr_accessor :pass_params
|
8
|
+
|
9
|
+
# A Hash of level names mapped to a method that is used to filter the
|
10
|
+
# available column values
|
11
|
+
attr_accessor :column_filters
|
12
|
+
|
13
|
+
# A Hash of level names mapped to a method that is used to filter the
|
14
|
+
# available row values
|
15
|
+
attr_accessor :row_filters
|
16
|
+
|
17
|
+
# An optional conditions String
|
18
|
+
attr_accessor :conditions
|
19
|
+
|
20
|
+
# Set the cube name
|
21
|
+
def cube_name=(name)
|
22
|
+
write_attribute(:cube_name, name)
|
23
|
+
@cube = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get the current cube instance
|
27
|
+
def cube
|
28
|
+
if @cube.nil?
|
29
|
+
cube_class = ActiveWarehouse::Cube.class_name(self.cube_name).constantize
|
30
|
+
@cube = cube_class.new
|
31
|
+
end
|
32
|
+
@cube
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get the fact class
|
36
|
+
def fact_class
|
37
|
+
cube.class.fact_class
|
38
|
+
end
|
39
|
+
|
40
|
+
# Get the column dimension class
|
41
|
+
def column_dimension_class
|
42
|
+
@column_dimension_class ||= fact_class.dimension_class(self.column_dimension_name)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Get the column hierarchy. Uses the first hierarchy in the column
|
46
|
+
# dimension if not specified
|
47
|
+
def column_hierarchy
|
48
|
+
ch = read_attribute(:column_hierarchy)
|
49
|
+
if ch.nil? || ch == 'NULL'
|
50
|
+
column_dimension_class.hierarchies.first
|
51
|
+
else
|
52
|
+
ch
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Get the column prefix. Returns 'c' if not specified.
|
57
|
+
def column_param_prefix
|
58
|
+
read_attribute(:column_param_prefix) || 'c'
|
59
|
+
end
|
60
|
+
|
61
|
+
# Get the row dimension class
|
62
|
+
def row_dimension_class
|
63
|
+
@row_dimension_class ||= fact_class.dimension_class(self.row_dimension_name)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Get the row hierarchy. Uses the first hierarchy in the row dimension if
|
67
|
+
# not specified
|
68
|
+
def row_hierarchy
|
69
|
+
read_attribute(:row_hierarchy) || row_dimension_class.hierarchies.first
|
70
|
+
end
|
71
|
+
|
72
|
+
# Get the row parameter prefix. Returns 'r' if not specified.
|
73
|
+
def row_param_prefix
|
74
|
+
read_attribute(:row_param_prefix) || 'r'
|
75
|
+
end
|
76
|
+
|
77
|
+
# Get the list of displayed fact attributes. If this value is not
|
78
|
+
# specified then all aggregate and calculated fields will be displayed
|
79
|
+
def fact_attributes
|
80
|
+
return read_attribute(:fact_attributes) if read_attribute(:fact_attributes)
|
81
|
+
fa = []
|
82
|
+
fact_class.aggregate_fields.each { |field| fa << field }
|
83
|
+
fact_class.calculated_fields.each { |field| fa << field }
|
84
|
+
fa
|
85
|
+
end
|
86
|
+
|
87
|
+
def column_filters
|
88
|
+
@column_filters ||= {}
|
89
|
+
end
|
90
|
+
|
91
|
+
def row_filters
|
92
|
+
@row_filters ||= {}
|
93
|
+
end
|
94
|
+
|
95
|
+
def pass_params
|
96
|
+
@pass_params ||= []
|
97
|
+
end
|
98
|
+
|
99
|
+
protected
|
100
|
+
# Callback which is invoked on each object returned from a call to the object's find method.
|
101
|
+
def after_find
|
102
|
+
from_storage
|
103
|
+
end
|
104
|
+
|
105
|
+
# Converts values for all columns which can store symbol values into strings. This is used to store
|
106
|
+
# the data in the database as a string rather than a YAML representation
|
107
|
+
def to_storage
|
108
|
+
symbol_attributes.each do |name|
|
109
|
+
self[name] = self[name].to_s if self[name]
|
110
|
+
end
|
111
|
+
list_attributes.each do |name|
|
112
|
+
self[name] = self[name].join(',') if self[name]
|
113
|
+
end
|
114
|
+
symbolized_list_attributes.each do |name|
|
115
|
+
self[name] = self[name].join(',') if self[name]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Converts values for all columns which store strings in the database to symbols.
|
120
|
+
def from_storage
|
121
|
+
symbol_attributes.each do |name|
|
122
|
+
self[name] = self[name].to_sym if self[name]
|
123
|
+
end
|
124
|
+
list_attributes.each do |name|
|
125
|
+
self[name] = self[name].split(/,/) if self[name]
|
126
|
+
end
|
127
|
+
symbolized_list_attributes.each do |name|
|
128
|
+
self[name] = self[name].split(/,/).collect { |v| v.to_sym } if self[name]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Attributes which should contain a symbol
|
133
|
+
def symbol_attributes
|
134
|
+
%w(cube_name column_dimension_name column_hierarchy row_dimension_name row_hierarchy)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Attributes which should contain a list of strings
|
138
|
+
def list_attributes
|
139
|
+
%w(column_constraints row_constraints)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Attributes which should contain a list of symbols
|
143
|
+
def symbolized_list_attributes
|
144
|
+
%w(fact_attributes)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ActiveWarehouse
|
2
|
+
module Report
|
3
|
+
|
4
|
+
class DataCell
|
5
|
+
|
6
|
+
attr_accessor :column_dimension_value, :row_dimension_value, :fact_attribute, :raw_value, :value
|
7
|
+
|
8
|
+
def initialize(column_dimension_value, row_dimension_value, fact_attribute, raw_value, value)
|
9
|
+
@column_dimension_value = column_dimension_value
|
10
|
+
@row_dimension_value = row_dimension_value
|
11
|
+
@fact_attribute = fact_attribute
|
12
|
+
@raw_value = raw_value
|
13
|
+
@value = value
|
14
|
+
end
|
15
|
+
|
16
|
+
def key
|
17
|
+
"#{column_dimension_value}_#{fact_attribute.label}".gsub(' ', '_').downcase
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|