activewarehouse 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/README +62 -17
  2. data/Rakefile +17 -0
  3. data/generators/bridge/USAGE +1 -0
  4. data/generators/bridge/bridge_generator.rb +46 -0
  5. data/generators/bridge/templates/fixture.yml +5 -0
  6. data/generators/bridge/templates/migration.rb +20 -0
  7. data/generators/bridge/templates/model.rb +3 -0
  8. data/generators/dimension/templates/unit_test.rb +0 -2
  9. data/generators/dimension_view/USAGE +1 -0
  10. data/generators/dimension_view/dimension_view_generator.rb +62 -0
  11. data/generators/dimension_view/templates/migration.rb +11 -0
  12. data/generators/dimension_view/templates/model.rb +3 -0
  13. data/generators/dimension_view/templates/unit_test.rb +10 -0
  14. data/init.rb +1 -0
  15. data/lib/active_warehouse.rb +24 -9
  16. data/lib/active_warehouse/{model/aggregate.rb → aggregate.rb} +29 -13
  17. data/lib/active_warehouse/builder/date_dimension_builder.rb +21 -6
  18. data/lib/active_warehouse/builder/random_data_builder.rb +204 -3
  19. data/lib/active_warehouse/compat/compat.rb +49 -0
  20. data/lib/active_warehouse/{model/cube.rb → cube.rb} +47 -17
  21. data/lib/active_warehouse/dimension.rb +296 -0
  22. data/lib/active_warehouse/dimension/bridge.rb +15 -0
  23. data/lib/active_warehouse/dimension/dimension_view.rb +11 -0
  24. data/lib/active_warehouse/dimension/hierarchical_dimension.rb +60 -0
  25. data/lib/active_warehouse/dimension/slowly_changing_dimension.rb +137 -0
  26. data/lib/active_warehouse/{model/fact.rb → fact.rb} +45 -10
  27. data/lib/active_warehouse/migrations.rb +1 -2
  28. data/lib/active_warehouse/report.rb +3 -0
  29. data/lib/active_warehouse/{model/report → report}/abstract_report.rb +0 -0
  30. data/lib/active_warehouse/{model/report → report}/chart_report.rb +0 -0
  31. data/lib/active_warehouse/{model/report → report}/table_report.rb +0 -0
  32. data/lib/active_warehouse/version.rb +2 -2
  33. data/lib/active_warehouse/view/report_helper.rb +2 -1
  34. data/tasks/active_warehouse_tasks.rake +54 -0
  35. metadata +43 -21
  36. data/doc/agg_queries.txt +0 -26
  37. data/doc/agg_queries_results.txt +0 -150
  38. data/doc/queries.txt +0 -35
  39. data/lib/active_warehouse/model.rb +0 -5
  40. data/lib/active_warehouse/model/dimension.rb +0 -3
  41. data/lib/active_warehouse/model/dimension/bridge.rb +0 -32
  42. data/lib/active_warehouse/model/dimension/dimension.rb +0 -152
  43. data/lib/active_warehouse/model/dimension/hierarchical_dimension.rb +0 -35
  44. data/lib/active_warehouse/model/report.rb +0 -3
@@ -0,0 +1,15 @@
1
+ module ActiveWarehouse #:nodoc
2
+ # Implements a bridge table.
3
+ class Bridge < ActiveRecord::Base
4
+ class << self
5
+ # Get the table name. By default the table name will be the name of the bridge in singular form.
6
+ #
7
+ # Example: DepartmentHierarchyBridge will have a table called department_hierarchy_bridge
8
+ def table_name
9
+ name = self.name.demodulize.underscore
10
+ set_table_name(name)
11
+ name
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module ActiveWarehouse #:nodoc
2
+ # DimensionViews represent role-playing dimensions in a data warehouse. These types of dimensions provide
3
+ # a view for an existing dimension. A common use is to provide a date dimension and then provide numerous
4
+ # role-playing dimensions implemented as views to the date dimension, such as Order Date Dimension,
5
+ # Shipping Date Dimension, etc.
6
+ class DimensionView < ActiveRecord::Base
7
+ class << self
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,60 @@
1
+ module ActiveWarehouse #:nodoc
2
+ # Implements a hierarchical dimension. Including the <tt>acts_as_hierarchical_dimension</tt> directive in
3
+ # a dimension will add methods for accessing the parent and children of any node in the hierarchy.
4
+ module HierarchicalDimension
5
+ def self.included(base) #:nodoc
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods #:nodoc
10
+ # Indicates that a dimension is a variable-depth hierarchy.
11
+ def acts_as_hierarchy_dimension
12
+ unless hierarchical_dimension?
13
+ class << self
14
+ # Get the bridge class for this dimension
15
+ def bridge_class
16
+ unless @bridge_class
17
+ unless Object.const_defined?(bridge_class_name.to_sym)
18
+ Object.const_set(bridge_class_name.to_sym, Class.new(ActiveWarehouse::Bridge))
19
+ end
20
+ @bridge_class = Object.const_get(bridge_class_name.to_sym)
21
+ end
22
+ @bridge_class
23
+ end
24
+
25
+ # Get the bridge class name for this hierarchical dimension
26
+ def bridge_class_name
27
+ name.gsub(/Dimension$/, '') + 'HierarchyBridge'
28
+ end
29
+ end
30
+ end
31
+ include InstanceMethods
32
+ end
33
+ alias :acts_as_hierarchical_dimension :acts_as_hierarchy_dimension
34
+
35
+ # Return true if this is a hierarchical dimension
36
+ def hierarchical_dimension?
37
+ self.included_modules.include?(InstanceMethods)
38
+ end
39
+ end
40
+
41
+ module InstanceMethods #:nodoc
42
+ # Get the parent for this node
43
+ def parent
44
+ self.class.find(:first,
45
+ :select => "a.*",
46
+ :joins => "a join #{self.class.bridge_class.table_name} b on a.id = b.parent_id",
47
+ :conditions => ['b.child_id = ? and b.levels_from_parent = 1', self.id])
48
+ end
49
+
50
+ # Get the children for this node
51
+ def children
52
+ self.class.find(:all,
53
+ :select => "a.*",
54
+ :joins => "a join #{self.class.bridge_class.table_name} b on a.id = b.child_id",
55
+ :conditions => ['b.parent_id = ? and b.levels_from_parent = 1', self.id])
56
+ end
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,137 @@
1
+ module ActiveWarehouse #:nodoc:
2
+ # Implements Type 2 Slowly Changing Dimensions.
3
+ #
4
+ # In a type 2 SCD, a new row is added each time a dimension entry requires an update. Three columns are required in
5
+ # the dimension table to support this:
6
+ #
7
+ # * latest_version - A boolean flag which indicates whether or not the row is the latest and current value
8
+ # * effective_date - A start date for when this row takes effect
9
+ # * expiration_date - An end date for when this row expires
10
+ #
11
+ # This module will override finder behavior in several ways. If used in a normal fashion, the find method will return
12
+ # the match row or rows with the latest_version flag set to true. You can also call the finder with the :valid_on
13
+ # option set indicating that you want the row that is valid on the given date.
14
+ #
15
+ # You can completely override the modified finder behavior using the :with_older option (set to true). You *must* include
16
+ # this option if you want to search for records which are not current (for example, using the find(id) version of the finder
17
+ # methods).
18
+ module SlowlyChangingDimension
19
+ def self.included(base) # :nodoc:
20
+ base.extend ClassMethods
21
+ end
22
+
23
+ module ClassMethods
24
+ # Indicate that the dimension is a Type 2 Slowly Changing Dimension (SDC).
25
+ #
26
+ # A word of warning:
27
+ #
28
+ # The expiration_date field must never be null. For the current effective record use the maximum date allowed.
29
+ # This is necessary because the find query used when :valid_on is specified is implemented using a between clause.
30
+ #
31
+ # Options:
32
+ # *<tt>:identifier</tt>:
33
+ # *<tt>:lastest_version</tt>: Define the attribute name which represents the latest version flag
34
+ # *<tt>:effective_date</tt>: Define the attribute name which represents the effective date column
35
+ # *<tt>:expiration_date</tt>: Define the attribute name which represents the expiration date column
36
+ #
37
+ def acts_as_slowly_changing_dimension(options = {})
38
+ unless slowly_changing_dimension? # don't let AR call this twice
39
+ cattr_accessor :identifier
40
+ cattr_accessor :latest_version_attribute
41
+ cattr_accessor :effective_date_attribute
42
+ cattr_accessor :expiration_date_attribute
43
+ self.identifier = options[:identifier] || :identifier
44
+ self.latest_version_attribute = options[:with] || :latest_version
45
+ self.effective_date_attribute = options[:effective_date_attribute] || :effective_date
46
+ self.expiration_date_attribute = options[:expiration_date_attribute] || :expiration_date
47
+ class << self
48
+ alias_method :find_every_with_older, :find_every
49
+ alias_method :calculate_with_older, :calculate
50
+ alias_method :core_validate_find_options, :validate_find_options
51
+ VALID_FIND_OPTIONS << :with_older
52
+ VALID_FIND_OPTIONS << :valid_on
53
+ VALID_FIND_OPTIONS << :valid_on_or_after
54
+ end
55
+ end
56
+ include InstanceMethods
57
+ end
58
+
59
+ # Return true if this dimension is a slowly changing dimension
60
+ def slowly_changing_dimension?
61
+ self.included_modules.include?(InstanceMethods)
62
+ end
63
+ end
64
+
65
+ module InstanceMethods #:nodoc:
66
+ def self.included(base) # :nodoc:
67
+ base.extend ClassMethods
68
+ end
69
+
70
+ def versions
71
+ self.class.find(:all,
72
+ :conditions => ["#{self.class.identifier} = ?", self.send(identifier)],
73
+ :with_older => true,
74
+ :order => "#{self.class.effective_date_attribute} asc")
75
+ end
76
+
77
+ module ClassMethods
78
+ def find_with_older(*args)
79
+ options = extract_options_from_args!(args)
80
+ validate_find_options(options)
81
+ set_readonly_option!(options)
82
+ options[:with_older] = true # yuck!
83
+
84
+ case args.first
85
+ when :first then find_initial(options)
86
+ when :all then find_every(options)
87
+ else find_from_ids(args, options)
88
+ end
89
+ end
90
+
91
+ def count_with_older(*args)
92
+ calculate_with_older(:count, *construct_count_options_from_legacy_args(*args))
93
+ end
94
+
95
+ def count(*args)
96
+ with_older_scope { count_with_older(*args) }
97
+ end
98
+
99
+ def calculate(*args)
100
+ with_older_scope { calculate_with_older(*args) }
101
+ end
102
+
103
+ protected
104
+ def with_older_scope(&block)
105
+ with_scope({:find => { :conditions =>
106
+ "#{table_name}.#{latest_version_attribute} = 1" } }, :merge, &block)
107
+ end
108
+
109
+ def with_valid_on_scope(valid_on, &block)
110
+ with_scope({:find => { :conditions =>
111
+ ["? between #{effective_date_attribute} " +
112
+ "and #{expiration_date_attribute}", valid_on]} }, :merge, &block)
113
+ end
114
+
115
+ def with_valid_on_or_after_scope(valid_on_or_after, &block)
116
+ with_scope({:find => {:conditions =>
117
+ ["#{effective_date_attribute} <= ? and #{expiration_date_attribute} > ?",
118
+ valid_on_or_after, valid_on_or_after]} }, :merge, &block)
119
+ end
120
+
121
+ private
122
+ # all find calls lead here
123
+ def find_every(options)
124
+ if options.include?(:valid_on)
125
+ with_valid_on_scope(options[:valid_on]) { find_every_with_older(options) }
126
+ elsif options.include?(:valid_on_or_after)
127
+ with_valid_on_or_after_scope(options[:valid_on_or_after]) { find_every_with_older(options) }
128
+ elsif options.include?(:with_older)
129
+ find_every_with_older(options)
130
+ else
131
+ with_older_scope { find_every_with_older(options) }
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -1,28 +1,56 @@
1
- module ActiveWarehouse
1
+ module ActiveWarehouse #:nodoc
2
+ # Facts represent business measures. A row in a fact table corresponds to set of measurements in a particular
3
+ # granularity along with the foreign keys connecting the fact to various dimensions. All measurements in a fact
4
+ # table must be at the same grain.
2
5
  class Fact < ActiveRecord::Base
3
-
4
6
  class << self
5
- attr_accessor :aggregate_fields, :aggregate_field_options, :calculated_fields, :calculated_field_options
7
+ # Array of aggregate field names
8
+ attr_accessor :aggregate_fields
9
+
10
+ # Hash of aggregate field options, where the key is the field name
11
+ # and the value is the Hash of options for that aggregate.
12
+ attr_accessor :aggregate_field_options
13
+
14
+ # Array of calculated field names
15
+ attr_accessor :calculated_fields
16
+
17
+ # Hash of calculated field options, where the key is the field name
18
+ # and the value is the Hash of options for that calculated field.
19
+ attr_accessor :calculated_field_options
6
20
 
7
21
  # Return a list of dimensions for this fact.
8
22
  #
9
23
  # Example:
10
24
  #
11
25
  # sales_fact
12
- # time_id
26
+ # date_id
13
27
  # region_id
14
28
  # sales_amount
15
29
  # number_items_sold
16
30
  #
17
- # Calling SalesFact.dimensions would return the list: ['time','region']
31
+ # Calling SalesFact.dimensions would return the list: [:date, :region]
18
32
  def dimensions
19
- dims = []
33
+ foreign_key_columns.collect { |c| c.name.gsub(/_id/, '').to_sym }
34
+ end
35
+
36
+ # Get all of the Column objects representing foreign key columns
37
+ #
38
+ # Example:
39
+ #
40
+ # sales_fact
41
+ # date_id
42
+ # region_id
43
+ # sales_amount
44
+ # number_items_sold
45
+ #
46
+ # Calling SalesFact.foreign_key_columns would return a list of column objects containing
47
+ # the date column and the region column.
48
+ def foreign_key_columns
49
+ fk_columns = []
20
50
  columns.each do |column|
21
- if column.name =~ /(.*)_id/
22
- dims << $1.to_sym
23
- end
51
+ fk_columns << column if column.name =~ /(.*)_id/
24
52
  end
25
- dims
53
+ fk_columns
26
54
  end
27
55
 
28
56
  # Get the time when the fact source file was last modified
@@ -49,6 +77,13 @@ module ActiveWarehouse
49
77
  class_name(name).constantize
50
78
  end
51
79
 
80
+ # Get the fact class for the specified value. The fact parameter may be a class,
81
+ # String or Symbol.
82
+ def to_fact(dimension)
83
+ return dimension if dimension.is_a?(Class) and dimension.superclass == Fact
84
+ return class_for_name(dimension)
85
+ end
86
+
52
87
  # Define an aggregate. Also aliased from aggregate()
53
88
  # * <tt>field</tt>: The field name
54
89
  # * <tt>options</tt>: A hash of options for the aggregate
@@ -1,7 +1,6 @@
1
1
  module ActiveWarehouse #:nodoc:
2
- # Responsible for migrating ActiveWarehouse
2
+ # Responsible for migrating ActiveWarehouse tables which are automatically created.
3
3
  class Migrator < ActiveRecord::Migrator
4
-
5
4
  class << self
6
5
  def schema_info_table_name #:nodoc:
7
6
  ActiveRecord::Base.table_name_prefix + 'activewarehouse_schema_info' + ActiveRecord::Base.table_name_suffix
@@ -0,0 +1,3 @@
1
+ require 'active_warehouse/report/abstract_report'
2
+ require 'active_warehouse/report/table_report'
3
+ require 'active_warehouse/report/chart_report'
@@ -1,7 +1,7 @@
1
- module ActiveWarehouse
1
+ module ActiveWarehouse #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 1
4
+ MINOR = 2
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
@@ -138,6 +138,7 @@ module ReportHelper
138
138
  end
139
139
  end
140
140
 
141
+ # TODO: implement chart rendering
141
142
  def render_chart_report(report, html_options)
142
143
  "Not Yet Implemented"
143
144
  end
@@ -190,7 +191,7 @@ module ReportHelper
190
191
  # Example:
191
192
  # sortable_column_header('SSN','ssn')
192
193
  # sortable_column_header('Name','name',{:onclick => 'doSomething();'}, {:title => 'Some Title'})
193
- def sortable_column_header(column_name, order_by, link_parameters={}, attributes={})
194
+ def sortable_column_header(column_name, order_by, link_parameters={}, attributes={}) # TODO get this thing back into the mix
194
195
  order = 'desc'
195
196
  if params[:order_by].to_s == order_by.to_s
196
197
  sorted = 'sorted'
@@ -1,4 +1,13 @@
1
1
  namespace :warehouse do
2
+ desc "Drop and create the current database"
3
+ task :recreate => :environment do
4
+ abcs = ActiveRecord::Base.configurations
5
+ ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
6
+ puts "Recreating #{ActiveRecord::Base.connection.current_database}"
7
+ ActiveRecord::Base.connection.recreate_database(ActiveRecord::Base.connection.current_database)
8
+ ActiveRecord::Base.connection.reconnect!
9
+ end
10
+
2
11
  desc "Build a 'standard' date dimension"
3
12
  task :build_date_dimension => :environment do
4
13
  abcs = ActiveRecord::Base.configurations
@@ -6,6 +15,8 @@ namespace :warehouse do
6
15
 
7
16
  start_date = (ENV['START_DATE'] ? Time.parse(ENV['START_DATE']) : Time.now.years_ago(5))
8
17
  end_date = (ENV['END_DATE'] ? Time.parse(ENV['END_DATE']) : Time.now )
18
+
19
+ puts "Building date dimension"
9
20
 
10
21
  ddb = ActiveWarehouse::Builder::DateDimensionBuilder.new(start_date, end_date)
11
22
  ddb.build.each do |record|
@@ -17,6 +28,34 @@ namespace :warehouse do
17
28
  end
18
29
  end
19
30
 
31
+ desc "Build random data for all facts and dimensions in the models directory, excluding date"
32
+ task :build_random_data => :environment do
33
+ abcs = ActiveRecord::Base.configurations
34
+ ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
35
+ require 'pp'
36
+
37
+ truncate = true if ENV['TRUNCATE']
38
+ name = ENV['NAME']
39
+
40
+ if name
41
+ build_and_load(name, truncate)
42
+ else
43
+ models_dir = File.join(File.dirname(__FILE__), '../../../../app/models')
44
+ Dir.glob(File.join(models_dir, "**", "*.rb")).each do |f|
45
+ name = File.basename(f, '.rb')
46
+ next unless name =~ /_dimension$|_fact$/
47
+ next if name == 'date_dimension'
48
+ build_and_load(name)
49
+ end
50
+ end
51
+ end
52
+
53
+ desc "Populate with test data"
54
+ task :populate => [:build_date_dimension, :build_random_data]
55
+
56
+ desc "Recreate, migrate and populate"
57
+ task :setup => [:recreate, :migrate, 'db:migrate', :populate]
58
+
20
59
  desc "Rebuild the warehouse" # TODO: consider moving this logic somewhere into a class and calling it from here
21
60
  task :rebuild => :environment do
22
61
  puts "Rebuilding data warehouse"
@@ -47,4 +86,19 @@ namespace :warehouse do
47
86
  migration_directory = File.join(File.dirname(__FILE__), '../db/migrations')
48
87
  ActiveWarehouse::Migrator.migrate(migration_directory, ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
49
88
  end
89
+ end
90
+
91
+ def build_and_load(name, truncate=false)
92
+ builder = ActiveWarehouse::Builder::RandomDataBuilder.new
93
+ puts "Building #{name}"
94
+ clazz = name.classify.constantize
95
+ if truncate # TODO: Handle through adapter by adding a truncate method to the adapter
96
+ clazz.connection.execute("TRUNCATE #{clazz.table_name}")
97
+ end
98
+ options = {:fk_limit => {'date_id' => DateDimension.count}}
99
+ builder.build(name, options).each do |record|
100
+ clazz.create(record)
101
+ end
102
+ rescue => e
103
+ puts "Unable to build #{name}: #{e}"
50
104
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
2
+ rubygems_version: 0.9.0.10
3
3
  specification_version: 1
4
4
  name: activewarehouse
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.0
7
- date: 2006-12-19 00:00:00 -05:00
6
+ version: 0.2.0
7
+ date: 2007-02-18 00:00:00 -05:00
8
8
  summary: Build data warehouses with Rails.
9
9
  require_paths:
10
10
  - lib
@@ -29,18 +29,24 @@ post_install_message:
29
29
  authors:
30
30
  - Anthony Eden
31
31
  files:
32
+ - init.rb
32
33
  - install.rb
33
34
  - README
34
35
  - TODO
35
36
  - Rakefile
36
37
  - db/migrations
37
38
  - db/migrations/001_create_table_reports.rb
38
- - doc/agg_queries.txt
39
- - doc/agg_queries_results.txt
40
- - doc/queries.txt
39
+ - generators/bridge
41
40
  - generators/cube
42
41
  - generators/dimension
42
+ - generators/dimension_view
43
43
  - generators/fact
44
+ - generators/bridge/bridge_generator.rb
45
+ - generators/bridge/templates
46
+ - generators/bridge/USAGE
47
+ - generators/bridge/templates/fixture.yml
48
+ - generators/bridge/templates/migration.rb
49
+ - generators/bridge/templates/model.rb
44
50
  - generators/cube/cube_generator.rb
45
51
  - generators/cube/templates
46
52
  - generators/cube/USAGE
@@ -53,6 +59,12 @@ files:
53
59
  - generators/dimension/templates/migration.rb
54
60
  - generators/dimension/templates/model.rb
55
61
  - generators/dimension/templates/unit_test.rb
62
+ - generators/dimension_view/dimension_view_generator.rb
63
+ - generators/dimension_view/templates
64
+ - generators/dimension_view/USAGE
65
+ - generators/dimension_view/templates/migration.rb
66
+ - generators/dimension_view/templates/model.rb
67
+ - generators/dimension_view/templates/unit_test.rb
56
68
  - generators/fact/fact_generator.rb
57
69
  - generators/fact/templates
58
70
  - generators/fact/USAGE
@@ -62,34 +74,35 @@ files:
62
74
  - generators/fact/templates/unit_test.rb
63
75
  - lib/active_warehouse
64
76
  - lib/active_warehouse.rb
77
+ - lib/active_warehouse/aggregate.rb
65
78
  - lib/active_warehouse/builder
66
79
  - lib/active_warehouse/builder.rb
80
+ - lib/active_warehouse/compat
67
81
  - lib/active_warehouse/core_ext
68
82
  - lib/active_warehouse/core_ext.rb
83
+ - lib/active_warehouse/cube.rb
84
+ - lib/active_warehouse/dimension
85
+ - lib/active_warehouse/dimension.rb
86
+ - lib/active_warehouse/fact.rb
69
87
  - lib/active_warehouse/migrations.rb
70
- - lib/active_warehouse/model
71
- - lib/active_warehouse/model.rb
88
+ - lib/active_warehouse/report
89
+ - lib/active_warehouse/report.rb
72
90
  - lib/active_warehouse/version.rb
73
91
  - lib/active_warehouse/view
74
92
  - lib/active_warehouse/view.rb
75
93
  - lib/active_warehouse/builder/date_dimension_builder.rb
76
94
  - lib/active_warehouse/builder/random_data_builder.rb
95
+ - lib/active_warehouse/compat/compat.rb
77
96
  - lib/active_warehouse/core_ext/time
78
97
  - lib/active_warehouse/core_ext/time.rb
79
98
  - lib/active_warehouse/core_ext/time/calculations.rb
80
- - lib/active_warehouse/model/aggregate.rb
81
- - lib/active_warehouse/model/cube.rb
82
- - lib/active_warehouse/model/dimension
83
- - lib/active_warehouse/model/dimension.rb
84
- - lib/active_warehouse/model/fact.rb
85
- - lib/active_warehouse/model/report
86
- - lib/active_warehouse/model/report.rb
87
- - lib/active_warehouse/model/dimension/bridge.rb
88
- - lib/active_warehouse/model/dimension/dimension.rb
89
- - lib/active_warehouse/model/dimension/hierarchical_dimension.rb
90
- - lib/active_warehouse/model/report/abstract_report.rb
91
- - lib/active_warehouse/model/report/chart_report.rb
92
- - lib/active_warehouse/model/report/table_report.rb
99
+ - lib/active_warehouse/dimension/bridge.rb
100
+ - lib/active_warehouse/dimension/dimension_view.rb
101
+ - lib/active_warehouse/dimension/hierarchical_dimension.rb
102
+ - lib/active_warehouse/dimension/slowly_changing_dimension.rb
103
+ - lib/active_warehouse/report/abstract_report.rb
104
+ - lib/active_warehouse/report/chart_report.rb
105
+ - lib/active_warehouse/report/table_report.rb
93
106
  - lib/active_warehouse/view/report_helper.rb
94
107
  - tasks/active_warehouse_tasks.rake
95
108
  test_files: []
@@ -142,3 +155,12 @@ dependencies:
142
155
  - !ruby/object:Gem::Version
143
156
  version: 1.12.5.5618
144
157
  version:
158
+ - !ruby/object:Gem::Dependency
159
+ name: rails_sql_views
160
+ version_requirement:
161
+ version_requirements: !ruby/object:Gem::Version::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: 0.1.0
166
+ version: