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,99 @@
|
|
1
|
+
== ActiveWarehouse
|
2
|
+
|
3
|
+
The ActiveWarehouse library provides classes and functions which help with
|
4
|
+
building Data Warehouses using Rails. It can be installed either as a plugin
|
5
|
+
or as a Gem.
|
6
|
+
|
7
|
+
To install as a plugin just use:
|
8
|
+
|
9
|
+
script/plugin install --force svn://rubyforge.org/var/svn/activewarehouse/activewarehouse/trunk
|
10
|
+
|
11
|
+
To get the latest edge version.
|
12
|
+
|
13
|
+
To install as a Gem, use:
|
14
|
+
|
15
|
+
gem install activewarehouse
|
16
|
+
|
17
|
+
On *nix you will need to run this command as root or better yet, using sudo.
|
18
|
+
|
19
|
+
Next, you will need to freeze or link the Gem to your Rails app. I prefer using
|
20
|
+
the gemsonrails project:
|
21
|
+
|
22
|
+
gem install gemsonrails
|
23
|
+
|
24
|
+
And then in your Rails app:
|
25
|
+
|
26
|
+
rake gems:link GEM=activewarehouse
|
27
|
+
|
28
|
+
It is possible that freezing the Gem to the Rails app may not work at all times. It is most often best to install as a plugin.
|
29
|
+
|
30
|
+
== Generators
|
31
|
+
|
32
|
+
ActiveWarehouse comes with several generators
|
33
|
+
|
34
|
+
script/generate fact Sales
|
35
|
+
script/generate fact sales
|
36
|
+
|
37
|
+
Creates a SalesFact class and a sales_facts table.
|
38
|
+
|
39
|
+
script/generate dimension Region
|
40
|
+
script/generate dimension region
|
41
|
+
|
42
|
+
Creates a RegionDimension class and a region_dimension table.
|
43
|
+
|
44
|
+
script/generate cube RegionalSales
|
45
|
+
script/generate cube regional_sales
|
46
|
+
|
47
|
+
Creates a RegionalSalesCube class.
|
48
|
+
|
49
|
+
script/generate bridge CustomerHierarchy
|
50
|
+
script/generate bridge customer_hierarchy
|
51
|
+
|
52
|
+
Creates a CustomerHierarchyBridge class.
|
53
|
+
|
54
|
+
script/generate dimension_view OrderDate Date
|
55
|
+
script/generate dimension_view order_date date
|
56
|
+
|
57
|
+
Creates an OrderDateDimension class which is represented by a view on top
|
58
|
+
of the DateDimension.
|
59
|
+
|
60
|
+
The rules for naming are as follows:
|
61
|
+
|
62
|
+
Facts:
|
63
|
+
Fact classes and tables follow the typical Rails rules: classes are singular
|
64
|
+
and tables are pluralized.
|
65
|
+
Both the class and table name are suffixed by "_fact".
|
66
|
+
Dimensions:
|
67
|
+
Dimension classes and tables are both singular.
|
68
|
+
Both the class name and the table name are suffixed by "_dimension".
|
69
|
+
Cube:
|
70
|
+
Cube class is singular. If a cube table is created it will also be singular.
|
71
|
+
Bridge:
|
72
|
+
Bridge classes and tables are both singular.
|
73
|
+
Both the class name and the table name are suffixed by "_bridge".
|
74
|
+
Dimension View:
|
75
|
+
Dimension View classes are singular. The underlying data structure is a view
|
76
|
+
on top of an existing dimension.
|
77
|
+
Both the class name and the view name are suffixed by "_dimension"
|
78
|
+
|
79
|
+
== ETL
|
80
|
+
|
81
|
+
The ActiveWarehouse plugin does not directly handle Extract-Transform-Load
|
82
|
+
processes, however the ActiveWarehouse ETL gem (installed separately) can help.
|
83
|
+
To install it use:
|
84
|
+
|
85
|
+
gem install activewarehouse-etl
|
86
|
+
|
87
|
+
Once again you should run this command as root or using sudo.
|
88
|
+
|
89
|
+
More information on the ETL process can be found at
|
90
|
+
http://activewarehouse.rubyforge.org/etl
|
91
|
+
|
92
|
+
== Tutorial
|
93
|
+
|
94
|
+
A tutorial for ActiveWarehouse is available online at
|
95
|
+
http://anthonyeden.com/2006/12/20/activewarehouse-example-with-rails-svn-logs
|
96
|
+
(Note that is is out of date.)
|
97
|
+
|
98
|
+
You can also get a demo from the ActiveWarehouse subversion repository. Look in
|
99
|
+
the SVN_ROOT/demo directory.
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/contrib/rubyforgepublisher'
|
6
|
+
require 'spec/version'
|
7
|
+
require 'spec/rake/spectask'
|
8
|
+
|
9
|
+
require File.join(File.dirname(__FILE__), 'lib/active_warehouse', 'version')
|
10
|
+
|
11
|
+
module AW
|
12
|
+
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
|
13
|
+
PKG_NAME = 'activewarehouse'
|
14
|
+
PKG_VERSION = ActiveWarehouse::VERSION::STRING + PKG_BUILD
|
15
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
16
|
+
PKG_DESTINATION = ENV["PKG_DESTINATION"] || "../#{PKG_NAME}"
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'Default: run tests and specs.'
|
20
|
+
task :default => [:test, :spec]
|
21
|
+
|
22
|
+
desc 'Test the active_warehouse plugin.'
|
23
|
+
Rake::TestTask.new(:test) do |t|
|
24
|
+
t.libs << 'lib'
|
25
|
+
t.pattern = 'test/**/*_test.rb'
|
26
|
+
t.verbose = true
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Run all specs"
|
30
|
+
Spec::Rake::SpecTask.new do |t|
|
31
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
32
|
+
t.spec_opts = ['--options', 'spec/spec.opts']
|
33
|
+
unless ENV['NO_RCOV']
|
34
|
+
t.rcov = true
|
35
|
+
t.rcov_dir = '../doc/output/coverage'
|
36
|
+
t.rcov_opts = ['--exclude', 'spec\/spec,bin\/spec,examples,\/var\/lib\/gems,\/Library\/Ruby,\.autotest']
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
namespace :rcov do
|
41
|
+
desc 'Measures test coverage'
|
42
|
+
task :test do
|
43
|
+
rm_f 'coverage.data'
|
44
|
+
mkdir 'coverage' unless File.exist?('coverage')
|
45
|
+
rcov = "rcov --aggregate coverage.data --text-summary -Ilib"
|
46
|
+
system("#{rcov} test/*_test.rb")
|
47
|
+
system("open coverage/index.html") if PLATFORM['darwin']
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
desc 'Generate documentation for the active_warehouse plugin.'
|
52
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
53
|
+
rdoc.rdoc_dir = 'rdoc'
|
54
|
+
rdoc.title = 'ActiveWarehouse'
|
55
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
56
|
+
rdoc.rdoc_files.include('README')
|
57
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
58
|
+
end
|
59
|
+
|
60
|
+
# Gem Spec
|
61
|
+
module AW
|
62
|
+
def self.package_files(package_prefix)
|
63
|
+
FileList[
|
64
|
+
"#{package_prefix}[a-zA-Z]*.rb",
|
65
|
+
"#{package_prefix}README",
|
66
|
+
"#{package_prefix}TODO",
|
67
|
+
"#{package_prefix}Rakefile",
|
68
|
+
"#{package_prefix}db/**/*",
|
69
|
+
"#{package_prefix}doc/**/*",
|
70
|
+
"#{package_prefix}generators/**/*",
|
71
|
+
"#{package_prefix}lib/**/*",
|
72
|
+
"#{package_prefix}tasks/**/*"
|
73
|
+
] - [ "#{package_prefix}test" ]
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.spec(package_prefix = '')
|
77
|
+
Gem::Specification.new do |s|
|
78
|
+
s.name = 'activewarehouse'
|
79
|
+
s.version = AW::PKG_VERSION
|
80
|
+
s.summary = "Build data warehouses with Rails."
|
81
|
+
s.description = <<-EOF
|
82
|
+
ActiveWarehouse extends Rails to provide functionality specific for building data warehouses.
|
83
|
+
EOF
|
84
|
+
|
85
|
+
s.add_dependency('rake', '>= 0.7.1')
|
86
|
+
s.add_dependency('fastercsv', '>= 1.1.0')
|
87
|
+
s.add_dependency('activesupport', '>= 1.3.1')
|
88
|
+
s.add_dependency('activerecord', '>= 1.14.4')
|
89
|
+
s.add_dependency('actionpack', '>= 1.12.5')
|
90
|
+
s.add_dependency('rails_sql_views', '>= 0.1.0')
|
91
|
+
s.add_dependency('adapter_extensions', '>= 0.1.0')
|
92
|
+
|
93
|
+
s.rdoc_options << '--exclude' << '.'
|
94
|
+
s.has_rdoc = false
|
95
|
+
|
96
|
+
s.files = package_files(package_prefix).to_a.delete_if {|f| f.include?('.svn')}
|
97
|
+
s.require_path = 'lib'
|
98
|
+
|
99
|
+
#s.bindir = "bin" # Use these for applications.
|
100
|
+
#s.executables = []
|
101
|
+
#s.default_executable = ""
|
102
|
+
|
103
|
+
s.author = "Anthony Eden"
|
104
|
+
s.email = "anthonyeden@gmail.com"
|
105
|
+
s.homepage = "http://activewarehouse.rubyforge.org"
|
106
|
+
s.rubyforge_project = "activewarehouse"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
Rake::GemPackageTask.new(AW.spec) do |pkg|
|
112
|
+
pkg.gem_spec = AW.spec
|
113
|
+
pkg.need_tar = true
|
114
|
+
pkg.need_zip = true
|
115
|
+
end
|
116
|
+
|
117
|
+
desc "Generate code statistics"
|
118
|
+
task :lines do
|
119
|
+
lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
|
120
|
+
|
121
|
+
for file_name in FileList["lib/**/*.rb"]
|
122
|
+
next if file_name =~ /vendor/
|
123
|
+
f = File.open(file_name)
|
124
|
+
|
125
|
+
while line = f.gets
|
126
|
+
lines += 1
|
127
|
+
next if line =~ /^\s*$/
|
128
|
+
next if line =~ /^\s*#/
|
129
|
+
codelines += 1
|
130
|
+
end
|
131
|
+
puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
|
132
|
+
|
133
|
+
total_lines += lines
|
134
|
+
total_codelines += codelines
|
135
|
+
|
136
|
+
lines, codelines = 0, 0
|
137
|
+
end
|
138
|
+
|
139
|
+
puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
|
140
|
+
end
|
141
|
+
|
142
|
+
desc "Publish the release files to RubyForge."
|
143
|
+
task :release => [ :package ] do
|
144
|
+
`rubyforge login`
|
145
|
+
|
146
|
+
for ext in %w( gem tgz zip )
|
147
|
+
release_command = "rubyforge add_release activewarehouse #{AW::PKG_NAME} 'REL #{AW::PKG_VERSION}' pkg/#{AW::PKG_NAME}-#{AW::PKG_VERSION}.#{ext}"
|
148
|
+
puts release_command
|
149
|
+
system(release_command)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
desc "Publish the API documentation"
|
154
|
+
task :pdoc => [:rdoc] do
|
155
|
+
Rake::SshDirPublisher.new("aeden@rubyforge.org", "/var/www/gforge-projects/activewarehouse/rdoc", "rdoc").upload
|
156
|
+
end
|
157
|
+
|
158
|
+
desc "Reinstall the gem from a local package copy"
|
159
|
+
task :reinstall => [:package] do
|
160
|
+
windows = RUBY_PLATFORM =~ /mswin/
|
161
|
+
sudo = windows ? '' : 'sudo'
|
162
|
+
gem = windows ? 'gem.bat' : 'gem'
|
163
|
+
`#{sudo} #{gem} uninstall -x -i #{AW::PKG_NAME}`
|
164
|
+
`#{sudo} #{gem} install pkg/#{AW::PKG_NAME}-#{AW::PKG_VERSION}`
|
165
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
TODO list:
|
2
|
+
|
3
|
+
* Modify the fact generator so that the migration has a map for foreign key and a map for fact attributes. The foreign keys can then automatically be indexed as that is pretty much standard behavior.
|
4
|
+
* Make the belongs_to connection between facts and dimensions automatic.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class CreateTableReports < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :table_reports do |t|
|
4
|
+
t.column :title, :string
|
5
|
+
t.column :cube_name, :string, :null => false
|
6
|
+
|
7
|
+
t.column :column_dimension_name, :string
|
8
|
+
t.column :column_hierarchy, :string
|
9
|
+
t.column :column_constraints, :text
|
10
|
+
t.column :column_stage, :integer
|
11
|
+
t.column :column_param_prefix, :string
|
12
|
+
|
13
|
+
t.column :row_dimension_name, :string
|
14
|
+
t.column :row_hierarchy, :string
|
15
|
+
t.column :row_constraints, :text
|
16
|
+
t.column :row_stage, :integer
|
17
|
+
t.column :row_param_prefix, :string
|
18
|
+
|
19
|
+
t.column :fact_attributes, :text
|
20
|
+
|
21
|
+
t.column :created_at, :datetime
|
22
|
+
t.column :updated_at, :datetime
|
23
|
+
end
|
24
|
+
end
|
25
|
+
def self.down
|
26
|
+
drop_table :table_reports
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
The following papers are relevant to building, storing and querying data cubes with large databases.
|
2
|
+
|
3
|
+
http://research.microsoft.com/research/pubs/view.aspx?msr_tr_id=MSR-TR-95-22
|
4
|
+
http://dbpubs.stanford.edu/pub/showDoc.Fulltext?lang=en&doc=1995-34&format=pdf&compression=&name=1995-34.pdf
|
@@ -0,0 +1 @@
|
|
1
|
+
./script/generate bridge NAME
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class BridgeGenerator < Rails::Generator::NamedBase
|
2
|
+
attr_accessor :file_name
|
3
|
+
|
4
|
+
default_options :skip_migration => false
|
5
|
+
|
6
|
+
def initialize(runtime_args, runtime_options = {})
|
7
|
+
super
|
8
|
+
|
9
|
+
@name = @name.tableize.singularize
|
10
|
+
@table_name = "#{@name}_bridge"
|
11
|
+
@class_name = "#{@name.camelize}Bridge"
|
12
|
+
@file_name = "#{@class_name.tableize.singularize}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def manifest
|
16
|
+
record do |m|
|
17
|
+
# Check for class naming collisions.
|
18
|
+
m.class_collisions class_path, "#{class_name}", "#{class_name}Test"
|
19
|
+
|
20
|
+
# Create required directories if necessary
|
21
|
+
m.directory File.join('app/models', class_path)
|
22
|
+
m.directory File.join('test/unit', class_path)
|
23
|
+
m.directory File.join('test/fixtures', class_path)
|
24
|
+
|
25
|
+
# Generate the files
|
26
|
+
m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
|
27
|
+
m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
|
28
|
+
m.template 'fixture.yml', File.join('test/fixtures', class_path, "#{table_name}.yml")
|
29
|
+
|
30
|
+
# Generate the migration unless :skip_migration option is specified
|
31
|
+
unless options[:skip_migration]
|
32
|
+
m.migration_template 'migration.rb', 'db/migrate', :assigns => {
|
33
|
+
:migration_name => "Create#{class_name.gsub(/::/, '')}"
|
34
|
+
}, :migration_file_name => "create_#{file_name.gsub(/\//, '_')}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
def add_options!(opt)
|
41
|
+
opt.separator ''
|
42
|
+
opt.separator 'Options:'
|
43
|
+
opt.on("--skip-migration",
|
44
|
+
"Don't generate a migration file for this bridge") { |v| options[:skip_migration] = v }
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class <%= migration_name %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
fields = {
|
4
|
+
# the following are the required bridge table columns for
|
5
|
+
# variable depth hierarchies. Do not change them unless you know
|
6
|
+
# what you are doing.
|
7
|
+
:parent_id => :integer,
|
8
|
+
:child_id => :integer,
|
9
|
+
:num_levels_from_parent => :integer,
|
10
|
+
:is_bottom => :boolean,
|
11
|
+
:is_top => :boolean
|
12
|
+
}
|
13
|
+
create_table :<%= table_name %> do |t|
|
14
|
+
fields.each do |name,type|
|
15
|
+
t.column name, type
|
16
|
+
end
|
17
|
+
end
|
18
|
+
fields.each do |name,type|
|
19
|
+
add_index :<%= table_name %>, name unless type == :text
|
20
|
+
end
|
21
|
+
add_index :<%= table_name %>, [:parent_id, :child_id, :num_levels_from_parent], :unique => true
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.down
|
25
|
+
drop_table :<%= table_name %>
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
./script/generate cube NAME
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class CubeGenerator < Rails::Generator::NamedBase
|
2
|
+
attr_accessor :file_name
|
3
|
+
|
4
|
+
def initialize(runtime_args, runtime_options = {})
|
5
|
+
super
|
6
|
+
|
7
|
+
@name = @name.underscore
|
8
|
+
@table_name = "#{@name}_cube"
|
9
|
+
@class_name = "#{@name.camelize}Cube"
|
10
|
+
@file_name = "#{@class_name.tableize.singularize}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def manifest
|
14
|
+
record do |m|
|
15
|
+
# Check for class naming collisions.
|
16
|
+
m.class_collisions class_path, "#{class_name}", "#{class_name}Test"
|
17
|
+
|
18
|
+
# Create required directories if necessary
|
19
|
+
m.directory File.join('app/models', class_path)
|
20
|
+
m.directory File.join('test/unit', class_path)
|
21
|
+
|
22
|
+
# Generate the files
|
23
|
+
m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
|
24
|
+
m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|