rubiks 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +12 -12
- data/Gemfile +2 -0
- data/README.md +90 -72
- data/lib/rubiks/calculated_measure.rb +26 -0
- data/lib/rubiks/cube.rb +80 -0
- data/lib/rubiks/dimension.rb +48 -0
- data/lib/rubiks/hierarchy.rb +46 -0
- data/lib/rubiks/jars/commons-collections.jar +0 -0
- data/lib/rubiks/jars/commons-dbcp.jar +0 -0
- data/lib/rubiks/jars/commons-logging.jar +0 -0
- data/lib/rubiks/jars/commons-math.jar +0 -0
- data/lib/rubiks/jars/commons-pool.jar +0 -0
- data/lib/rubiks/jars/commons-vfs.jar +0 -0
- data/lib/rubiks/jars/eigenbase-properties.jar +0 -0
- data/lib/rubiks/jars/eigenbase-resgen.jar +0 -0
- data/lib/rubiks/jars/eigenbase-xom.jar +0 -0
- data/lib/rubiks/jars/log4j.jar +0 -0
- data/lib/rubiks/jars/mondrian.jar +0 -0
- data/lib/rubiks/jars/olap4j-1.2.0-SNAPSHOT.jar +0 -0
- data/lib/rubiks/jars/olap4j-xmla-1.2.0-SNAPSHOT.jar +0 -0
- data/lib/rubiks/jars/olap4j-xmla.jar.orig +0 -0
- data/lib/rubiks/jars/olap4j-xmlaserver-0.0.1-SNAPSHOT.jar +0 -0
- data/lib/rubiks/jars/olap4j.jar.orig +0 -0
- data/lib/rubiks/jars/postgresql-9.2-1002.jdbc3.jar +0 -0
- data/lib/rubiks/jars/postgresql-9.2-1002.jdbc4.jar +0 -0
- data/lib/rubiks/level.rb +57 -0
- data/lib/rubiks/measure.rb +28 -0
- data/lib/rubiks/mondrian/cell_set.rb +148 -0
- data/lib/rubiks/mondrian/connection.rb +131 -0
- data/lib/rubiks/mondrian/errors.rb +56 -0
- data/lib/rubiks/mondrian/jars/commons-collections-3.2.jar +0 -0
- data/lib/rubiks/mondrian/jars/commons-dbcp-1.2.2.jar +0 -0
- data/lib/rubiks/mondrian/jars/commons-logging-1.1.1.jar +0 -0
- data/lib/rubiks/mondrian/jars/commons-math-1.2.jar +0 -0
- data/lib/rubiks/mondrian/jars/commons-pool-1.4.jar +0 -0
- data/lib/rubiks/mondrian/jars/eigenbase-properties-1.1.2.jar +0 -0
- data/lib/rubiks/mondrian/jars/eigenbase-resgen-1.3.1.jar +0 -0
- data/lib/rubiks/mondrian/jars/eigenbase-xom-1.3.1.jar +0 -0
- data/lib/rubiks/mondrian/jars/log4j-1.2.17.jar +0 -0
- data/lib/rubiks/mondrian/jars/mondrian-4.0.0-SNAPSHOT.jar +0 -0
- data/lib/rubiks/mondrian/jars/olap4j-1.2.0-SNAPSHOT.jar +0 -0
- data/lib/rubiks/mondrian/jars/olap4j-xmla-1.2.0-SNAPSHOT.jar +0 -0
- data/lib/rubiks/mondrian/jars/olap4j-xmlaserver-0.0.1-SNAPSHOT.jar +0 -0
- data/lib/rubiks/mondrian/member.rb +107 -0
- data/lib/rubiks/mondrian.rb +44 -0
- data/lib/rubiks/named_object.rb +121 -0
- data/lib/rubiks/schema.rb +28 -0
- data/lib/rubiks/version.rb +1 -1
- data/lib/rubiks.rb +28 -4
- data/rubiks.gemspec +2 -1
- data/spec/examples/simple_mondrian_schema_spec.rb +56 -0
- data/spec/rubiks/calculated_measure_spec.rb +12 -0
- data/spec/rubiks/cube_spec.rb +29 -0
- data/spec/rubiks/dimension_spec.rb +12 -0
- data/spec/rubiks/hierarchy_spec.rb +15 -0
- data/spec/rubiks/level_spec.rb +20 -0
- data/spec/rubiks/measure_spec.rb +11 -0
- data/spec/rubiks/schema_spec.rb +32 -0
- data/spec/spec_helper.rb +10 -3
- data/spec/support/shared_examples.rb +12 -0
- metadata +85 -47
- data/lib/rubiks/examples.rb +0 -61
- data/lib/rubiks/nodes/annotated_node.rb +0 -26
- data/lib/rubiks/nodes/calculated_member.rb +0 -81
- data/lib/rubiks/nodes/cube.rb +0 -149
- data/lib/rubiks/nodes/dimension.rb +0 -72
- data/lib/rubiks/nodes/hierarchy.rb +0 -100
- data/lib/rubiks/nodes/level.rb +0 -133
- data/lib/rubiks/nodes/measure.rb +0 -75
- data/lib/rubiks/nodes/schema.rb +0 -72
- data/lib/rubiks/nodes/validated_node.rb +0 -79
- data/spec/examples/mondrian_docs_example_spec.rb +0 -108
- data/spec/examples/simple_mondrian_example_spec.rb +0 -84
- data/spec/rubiks/nodes/annotated_node_spec.rb +0 -24
- data/spec/rubiks/nodes/calculated_member_spec.rb +0 -50
- data/spec/rubiks/nodes/cube_spec.rb +0 -63
- data/spec/rubiks/nodes/dimension_spec.rb +0 -41
- data/spec/rubiks/nodes/hierarchy_spec.rb +0 -48
- data/spec/rubiks/nodes/level_spec.rb +0 -93
- data/spec/rubiks/nodes/measure_spec.rb +0 -55
- data/spec/rubiks/nodes/schema_spec.rb +0 -38
- data/spec/rubiks/nodes/validated_node_spec.rb +0 -49
- data/spec/support/examples/mondrian_docs.yml +0 -36
- data/spec/support/examples/shared_dimensions.yml +0 -45
- data/spec/support/matchers/be_like.rb +0 -24
- data/spec/support/schema_context.rb +0 -59
data/CHANGELOG.md
CHANGED
@@ -1,26 +1,26 @@
|
|
1
|
-
0.0
|
2
|
-
|
1
|
+
## 0.1.0
|
2
|
+
* Remove RLTK
|
3
|
+
* Generate Mondrian 3 schema
|
4
|
+
* Generate JSON schema
|
5
|
+
* Include Mondrian
|
6
|
+
|
7
|
+
## 0.0.6
|
3
8
|
* [0.0.6 release](https://github.com/moneydesktop/rubiks/pull/3)
|
4
9
|
* [Nodes deep_dup the input hash in .new_from_hash](https://github.com/moneydesktop/rubiks/commit/81b2d68eddf5551abd0f360aee4c91d237e10c3c)
|
5
10
|
|
6
|
-
0.0.5
|
7
|
-
-----
|
11
|
+
## 0.0.5
|
8
12
|
* [0.0.5 release](https://github.com/moneydesktop/rubiks/pull/2)
|
9
13
|
|
10
|
-
0.0.4
|
11
|
-
-----
|
14
|
+
## 0.0.4
|
12
15
|
* [Bump to v0.0.4](https://github.com/moneydesktop/rubiks/commit/38dfd1f82e947f39457670adfdc6ca67da2728c6)
|
13
16
|
* [Add GemVersion badge to README](https://github.com/moneydesktop/rubiks/commit/2d92097c4ba73d92690fab78455fc7db6ed0b3d9)
|
14
17
|
|
15
|
-
0.0.3
|
16
|
-
-----
|
18
|
+
## 0.0.3
|
17
19
|
* [Bump to v0.0.3](https://github.com/moneydesktop/rubiks/commit/23ceb29936f663605527a12ca2d2a5c623abe99e)
|
18
20
|
* Need to fill in other commits here
|
19
21
|
|
20
|
-
0.0.2
|
21
|
-
-----
|
22
|
+
## 0.0.2
|
22
23
|
* [Bump to v0.0.2](https://github.com/moneydesktop/rubiks/commit/14a55449be9552268c66cbf8b902af02cf7b73c6)
|
23
24
|
|
24
|
-
0.0.1
|
25
|
-
-----
|
25
|
+
## 0.0.1
|
26
26
|
* [Initial RubyGem project](https://github.com/moneydesktop/rubiks/commit/fa8be4badf70e86fda7e14bf23f9230a926893d2)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -12,102 +12,120 @@
|
|
12
12
|
[codeclimate]: https://codeclimate.com/github/moneydesktop/rubiks
|
13
13
|
[coveralls]: https://coveralls.io/r/moneydesktop/rubiks
|
14
14
|
|
15
|
-
|
15
|
+
[jruby]: http://jruby.org
|
16
|
+
[wiki_cube]: http://en.wikipedia.org/wiki/OLAP_cube
|
17
|
+
[wiki_olap]: http://en.wikipedia.org/wiki/Online_analytical_processing
|
18
|
+
[wiki_mdx]: http://en.wikipedia.org/wiki/MultiDimensional_eXpressions
|
19
|
+
[wiki_open_source]: http://en.wikipedia.org/wiki/Open-source_software
|
20
|
+
[wiki_java]: http://en.wikipedia.org/wiki/Java_(programming_language)
|
21
|
+
[wiki_data_warehouse]: http://en.wikipedia.org/wiki/Data_warehouse
|
22
|
+
[wiki_star_schema]: http://en.wikipedia.org/wiki/Star_schema
|
23
|
+
[wiki_dimensional_modeling]: http://en.wikipedia.org/wiki/Dimensional_modeling
|
24
|
+
[postgresql]: http://www.postgresql.org
|
25
|
+
[mondrian]: http://mondrian.pentaho.com
|
26
|
+
[mondrian_schema]: http://mondrian.pentaho.com/documentation/schema.php
|
27
|
+
[rails]: http://rubyonrails.org
|
16
28
|
|
17
|
-
|
29
|
+
Rubiks is a [Online Analytical Processing](wiki_olap) ( **OLAP** ) library written in [JRuby](jruby).
|
30
|
+
It runs on top of [Mondrian](mondrian) (an [Open-source](wiki_open_source) [OLAP](wiki_olap) server
|
31
|
+
written in [Java](wiki_java)) and provides the ability to:
|
18
32
|
|
19
|
-
|
20
|
-
|
21
|
-
|
33
|
+
* define a [OLAP](wiki_olap) schema in Ruby
|
34
|
+
* generate a [Mondrian XML schema](mondrian_schema) from this definition
|
35
|
+
* execute [MultiDimensional eXpressions](wiki_mdx) ( **MDX** ) queries against the OLAP server
|
22
36
|
|
23
|
-
gem 'rubiks'
|
24
37
|
|
25
|
-
|
38
|
+
### Assumptions
|
26
39
|
|
27
|
-
|
40
|
+
* You are using [JRuby](jruby)
|
41
|
+
* You are using [PostgreSQL](postgresql)
|
42
|
+
* You have designed and populated your [Data Warehouse](wiki_data_warehouse) (see [Dimensional Modeling](wiki_dimensional_modeling) and [Star Schema](wiki_star_schema))
|
43
|
+
* You are using [Ruby on Rails](rails) database naming conventions
|
28
44
|
|
29
|
-
After installing the gem, fire up an IRB session with `irb` or `bundle exec irb` if you are using Bundler, and follow this (or even paste it into your session):
|
30
45
|
|
31
|
-
|
32
|
-
require 'rubiks/examples'
|
46
|
+
### Installation
|
33
47
|
|
34
|
-
|
48
|
+
Run `gem install rubiks` to install the gem on its own.
|
35
49
|
|
36
|
-
|
50
|
+
Or you can add the following to your Gemfile and run the `bundle` command to install it.
|
37
51
|
|
38
|
-
|
52
|
+
gem 'rubiks'
|
39
53
|
|
40
|
-
puts md.to_xml # see the XML section below
|
41
|
-
```
|
42
54
|
|
43
|
-
|
44
|
-
|
45
|
-
```yaml
|
46
|
-
cubes:
|
47
|
-
- name: sales
|
48
|
-
dimensions:
|
49
|
-
- name: date
|
50
|
-
hierarchies:
|
51
|
-
- name: year_quarter_month
|
52
|
-
levels:
|
53
|
-
- name: year
|
54
|
-
column: the_year
|
55
|
-
data_type: numeric
|
56
|
-
|
57
|
-
- name: quarter
|
58
|
-
data_type: string
|
59
|
-
|
60
|
-
- name: month
|
61
|
-
column: month_of_year
|
62
|
-
data_type: Numeric
|
63
|
-
|
64
|
-
measures:
|
65
|
-
- name: unit_sales
|
66
|
-
aggregator: sum
|
67
|
-
format_string: '#,###'
|
68
|
-
|
69
|
-
- name: store_sales
|
70
|
-
aggregator: sum
|
71
|
-
format_string: '#,###'
|
72
|
-
|
73
|
-
- name: store_cost
|
74
|
-
aggregator: sum
|
75
|
-
format_string: '#,###'
|
76
|
-
|
77
|
-
calculated_members:
|
78
|
-
- name: profit
|
79
|
-
dimension: measures
|
80
|
-
formula: '[Measures].[Store Sales] / [Measures].[Store Cost]'
|
81
|
-
format_string: '$#,##0.00'
|
82
|
-
```
|
55
|
+
### Schema Example
|
83
56
|
|
84
|
-
|
57
|
+
After installing the gem, fire up an IRB session with `irb` or `bundle exec irb` if you are using Bundler, and follow this (or even paste it into your session):
|
85
58
|
|
59
|
+
```ruby
|
60
|
+
require 'rubiks'
|
61
|
+
|
62
|
+
schema = ::Rubiks::Schema.define :banking do
|
63
|
+
cube :transactions do
|
64
|
+
dimension :date, :type => 'TimeDimension' do
|
65
|
+
hierarchy :yqmwd, :caption => 'YQMWD' do
|
66
|
+
level :year, :level_type => 'TimeYears', :type => :numeric, :contiguous => true
|
67
|
+
level :quarter, :level_type => 'TimeQuarters', :type => :numeric, :contiguous => true, :cardinality => :low
|
68
|
+
level :month, :level_type => 'TimeMonths', :type => :numeric, :contiguous => true
|
69
|
+
level :week, :level_type => 'TimeWeeks', :type => :numeric, :column => :week_of_month, :contiguous => true, :cardinality => :low
|
70
|
+
level :day, :level_type => 'TimeDays', :type => :numeric, :contiguous => true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
dimension :account do
|
75
|
+
hierarchy :account_type do
|
76
|
+
level :asset_liability, :cardinality => :low
|
77
|
+
level :account_type
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
measure :count, :column => :quantity
|
82
|
+
measure :amount, :aggregator => :sum, :format_string => '$#,###'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
puts schema.to_xml
|
87
|
+
```
|
88
|
+
You should see this XML:
|
86
89
|
|
87
90
|
```xml
|
88
91
|
<?xml version="1.0" encoding="UTF-8"?>
|
89
|
-
<schema name="
|
90
|
-
<cube name="
|
91
|
-
<table name="
|
92
|
-
<dimension name="Date" foreignKey="date_id">
|
93
|
-
<hierarchy name="
|
92
|
+
<schema name="Banking">
|
93
|
+
<cube name="Transactions">
|
94
|
+
<table name="view_transactions"/>
|
95
|
+
<dimension name="Date" foreignKey="date_id" type="TimeDimension">
|
96
|
+
<hierarchy name="YQMWD" hasAll="true" primaryKey="id">
|
94
97
|
<table name="view_dates"/>
|
95
|
-
<level name="Year" column="
|
96
|
-
<level name="Quarter" column="quarter" type="
|
97
|
-
<level name="Month" column="
|
98
|
+
<level name="Year" column="year" levelType="TimeYears" type="Numeric"/>
|
99
|
+
<level name="Quarter" column="quarter" levelType="TimeQuarters" type="Numeric"/>
|
100
|
+
<level name="Month" column="month" levelType="TimeMonths" type="Numeric"/>
|
101
|
+
<level name="Week" column="week_of_month" levelType="TimeWeeks" type="Numeric"/>
|
102
|
+
<level name="Day" column="day" levelType="TimeDays" type="Numeric"/>
|
103
|
+
</hierarchy>
|
104
|
+
</dimension>
|
105
|
+
<dimension name="Account" foreignKey="account_id">
|
106
|
+
<hierarchy name="Account Type" hasAll="true" primaryKey="id">
|
107
|
+
<table name="view_accounts"/>
|
108
|
+
<level name="Asset Liability" column="asset_liability"/>
|
109
|
+
<level name="Account Type" column="account_type"/>
|
98
110
|
</hierarchy>
|
99
111
|
</dimension>
|
100
|
-
<measure name="
|
101
|
-
<measure name="
|
102
|
-
<measure name="Store Cost" aggregator="sum" formatString="#,###" column="store_cost"/>
|
103
|
-
<calculatedMember name="Profit" dimension="Measures" formula="[Measures].[Store Sales] / [Measures].[Store Cost]">
|
104
|
-
<calculatedMemberProperty name="FORMAT_STRING" value="$#,##0.00"/>
|
105
|
-
</calculatedMember>
|
112
|
+
<measure name="Count" column="quantity" aggregator="count"/>
|
113
|
+
<measure name="Amount" column="amount" aggregator="sum" formatString="$#,###"/>
|
106
114
|
</cube>
|
107
115
|
</schema>
|
108
116
|
```
|
109
117
|
|
110
|
-
|
118
|
+
|
119
|
+
### Similar projects
|
120
|
+
|
121
|
+
Check out these projects (which have been super helpful in working on Rubiks):
|
122
|
+
|
123
|
+
* [Mondrian (git)](https://github.com/pentaho/mondrian) - source code for Mondrian on GitHub
|
124
|
+
* [mondrian-olap](https://github.com/rsim/mondrian-olap) - a RubyGem wrapping Mondrian
|
125
|
+
* [Saiku](http://analytical-labs.com) ([Saiku on GitHub](https://github.com/OSBI/saiku)) - a modular open-source analysis suite offering lightweight OLAP which remains easily embeddable, extendable and configurable.
|
126
|
+
|
127
|
+
|
128
|
+
### Contributing
|
111
129
|
|
112
130
|
1. Fork it
|
113
131
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ::Rubiks
|
2
|
+
|
3
|
+
class CalculatedMeasure < NamedObject
|
4
|
+
def formula(new_value=nil, options={})
|
5
|
+
@formula = new_value.to_s if new_value.present?
|
6
|
+
@formula ||= @options[:formula]
|
7
|
+
end
|
8
|
+
|
9
|
+
def format_string(new_value=nil, options={})
|
10
|
+
@format_string = new_value.to_s if new_value.present?
|
11
|
+
@format_string ||= @options[:format_string]
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_xml(builder = nil)
|
15
|
+
builder = builder || new_builder
|
16
|
+
|
17
|
+
xml_attrs = default_xml_attributes
|
18
|
+
xml_attrs[:dimension] = 'Measures'
|
19
|
+
xml_attrs[:formula] = formula if formula.present?
|
20
|
+
xml_attrs[:formatString] = format_string if format_string.present?
|
21
|
+
|
22
|
+
builder.calculatedMember(xml_attrs)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/lib/rubiks/cube.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module ::Rubiks
|
2
|
+
|
3
|
+
class Cube < NamedObject
|
4
|
+
def time_dimension(new_value=nil)
|
5
|
+
@time_dimension = new_value.to_s if new_value.present?
|
6
|
+
@time_dimension ||= @options[:time_dimension]
|
7
|
+
end
|
8
|
+
|
9
|
+
def person_dimension(new_value=nil)
|
10
|
+
@person_dimension = new_value.to_s if new_value.present?
|
11
|
+
@person_dimension ||= @options[:person_dimension]
|
12
|
+
end
|
13
|
+
|
14
|
+
def count_measure(new_value=nil)
|
15
|
+
@count_measure = new_value.to_s if new_value.present?
|
16
|
+
@count_measure ||= @options[:count_measure]
|
17
|
+
end
|
18
|
+
|
19
|
+
def person_count_measure(new_value=nil)
|
20
|
+
@person_count_measure = new_value.to_s if new_value.present?
|
21
|
+
@person_count_measure ||= @options[:person_count_measure]
|
22
|
+
end
|
23
|
+
|
24
|
+
def dimensions
|
25
|
+
@dimensions ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
def dimension(dimension_name, options={}, &block)
|
29
|
+
dimensions.push ::Rubiks::Dimension.find_or_create(dimension_name, options, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def measures
|
33
|
+
@measures ||= []
|
34
|
+
end
|
35
|
+
|
36
|
+
def measure(measure_name, options={}, &block)
|
37
|
+
measures.push ::Rubiks::Measure.find_or_create(measure_name, options, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def calculated_measures
|
41
|
+
@calculated_measures ||= []
|
42
|
+
end
|
43
|
+
|
44
|
+
def calculated_measure(calculated_measure_name, options={}, &block)
|
45
|
+
calculated_measures.push ::Rubiks::CalculatedMeasure.find_or_create(calculated_measure_name, options, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
def json_hash
|
49
|
+
hash = default_json_attributes.merge(
|
50
|
+
:time_dimension => time_dimension.to_s,
|
51
|
+
:person_dimension => person_dimension.to_s,
|
52
|
+
:count_measure => count_measure.to_s,
|
53
|
+
:person_count_measure => person_count_measure.to_s,
|
54
|
+
:dimensions => dimensions.map{ |dim| dim.json_hash },
|
55
|
+
:measures => json_measures
|
56
|
+
)
|
57
|
+
hash.delete_if { |key,value| value.nil? || value.blank? }
|
58
|
+
hash.stringify_keys!
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_xml(builder = nil)
|
62
|
+
builder = builder || new_builder
|
63
|
+
|
64
|
+
builder.cube(default_xml_attributes) do
|
65
|
+
builder.table(:name => table)
|
66
|
+
dimensions.each{ |dimension| dimension.to_xml(builder) }
|
67
|
+
measures.each{ |measure| measure.to_xml(builder) }
|
68
|
+
calculated_measures.each{ |measure| measure.to_xml(builder) }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def json_measures
|
73
|
+
json_measures = []
|
74
|
+
json_measures.push(*measures.map{ |m| m.json_hash })
|
75
|
+
json_measures.push(*calculated_measures.map{ |cm| cm.json_hash })
|
76
|
+
json_measures
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ::Rubiks
|
2
|
+
|
3
|
+
class Dimension < NamedObject
|
4
|
+
def degenerate(new_value=nil)
|
5
|
+
@degenerate = new_value.to_s if new_value.present?
|
6
|
+
@degenerate ||= @options[:degenerate]
|
7
|
+
end
|
8
|
+
|
9
|
+
def type(new_value=nil)
|
10
|
+
@type = new_value.to_s if new_value.present?
|
11
|
+
@type ||= @options[:type]
|
12
|
+
end
|
13
|
+
|
14
|
+
def hierarchies
|
15
|
+
@hierarchies ||= []
|
16
|
+
end
|
17
|
+
|
18
|
+
def hierarchy(hierarchy_name, options={}, &block)
|
19
|
+
options.merge!(:table => degenerate ? 'degenerate' : self.table)
|
20
|
+
hierarchies.push ::Rubiks::Hierarchy.find_or_create(hierarchy_name, options, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def json_hash
|
24
|
+
hash = default_json_attributes.merge(
|
25
|
+
:hierarchies => hierarchies.map{ |hier| hier.json_hash }
|
26
|
+
)
|
27
|
+
hash[:type] = type.to_s if type.present?
|
28
|
+
hash.delete_if { |key,value| value.nil? }
|
29
|
+
hash.stringify_keys!
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_xml(builder = nil)
|
33
|
+
builder = builder || new_builder
|
34
|
+
|
35
|
+
xml_attrs = default_xml_attributes
|
36
|
+
if self.degenerate
|
37
|
+
xml_attrs.delete(:table)
|
38
|
+
else
|
39
|
+
xml_attrs[:foreignKey] = "#{name}_id"
|
40
|
+
end
|
41
|
+
xml_attrs[:type] = type if type.present?
|
42
|
+
builder.dimension(xml_attrs) do
|
43
|
+
hierarchies.each{ |hierarchy| hierarchy.to_xml(builder) }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ::Rubiks
|
2
|
+
|
3
|
+
class Hierarchy < ::Rubiks::NamedObject
|
4
|
+
def levels
|
5
|
+
@levels ||= []
|
6
|
+
end
|
7
|
+
|
8
|
+
def level(level_name, options={}, &block)
|
9
|
+
levels.push ::Rubiks::Level.find_or_create(level_name, options, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def all_member_name(new_value=nil)
|
13
|
+
@all_member_name = new_value.to_s if new_value.present?
|
14
|
+
@all_member_name ||= true
|
15
|
+
end
|
16
|
+
|
17
|
+
def has_all(new_value=nil)
|
18
|
+
@has_all = new_value.to_s if new_value.present?
|
19
|
+
@has_all ||= true
|
20
|
+
end
|
21
|
+
|
22
|
+
def json_hash
|
23
|
+
hash = default_json_attributes.merge(
|
24
|
+
:levels => levels.map{ |lvl| lvl.json_hash }
|
25
|
+
)
|
26
|
+
hash.delete_if { |key,value| value.nil? }
|
27
|
+
hash.stringify_keys!
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_xml(builder = nil)
|
31
|
+
builder = builder || new_builder
|
32
|
+
|
33
|
+
xml_attrs = default_xml_attributes.merge(:hasAll => has_all.to_s)
|
34
|
+
xml_attrs[:primaryKey] = 'id' unless degenerate?
|
35
|
+
builder.hierarchy(xml_attrs) do
|
36
|
+
builder.table(:name => table) unless degenerate?
|
37
|
+
levels.each{ |level| level.to_xml(builder) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def degenerate?
|
42
|
+
table == 'degenerate'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/rubiks/level.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module ::Rubiks
|
2
|
+
|
3
|
+
class Level < ::Rubiks::NamedObject
|
4
|
+
def cardinality(new_value=nil)
|
5
|
+
@cardinality = new_value.to_s if new_value.present?
|
6
|
+
@cardinality ||= @options[:cardinality]
|
7
|
+
end
|
8
|
+
|
9
|
+
def contiguous(new_value=nil)
|
10
|
+
@contiguous = new_value.to_s if new_value.present?
|
11
|
+
@contiguous ||= @options.key?(:contiguous) ? @options[:contiguous].to_s : nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def column(new_value=nil)
|
15
|
+
@column = new_value.to_s if new_value.present?
|
16
|
+
@column ||= @options[:column] || name
|
17
|
+
end
|
18
|
+
|
19
|
+
def name_column(new_value=nil)
|
20
|
+
@name_column = new_value.to_s if new_value.present?
|
21
|
+
@name_column ||= @options[:name_column]
|
22
|
+
end
|
23
|
+
|
24
|
+
def ordinal_column(new_value=nil)
|
25
|
+
@ordinal_column = new_value.to_s if new_value.present?
|
26
|
+
@ordinal_column ||= @options[:ordinal_column]
|
27
|
+
end
|
28
|
+
|
29
|
+
def level_type(new_value=nil)
|
30
|
+
@level_type = new_value.to_s if new_value.present?
|
31
|
+
@level_type ||= @options[:level_type]
|
32
|
+
end
|
33
|
+
|
34
|
+
def type(new_value=nil)
|
35
|
+
@type = new_value if new_value.present?
|
36
|
+
@type ||= @options[:type]
|
37
|
+
end
|
38
|
+
|
39
|
+
def json_hash
|
40
|
+
hash = default_json_attributes
|
41
|
+
hash[:cardinality] = cardinality.to_s if cardinality.present?
|
42
|
+
hash[:visible] = visible if visible.present? && visible == 'false'
|
43
|
+
hash[:contiguous] = contiguous if contiguous.present? && contiguous == 'true'
|
44
|
+
hash.stringify_keys!
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_xml(builder = nil)
|
48
|
+
builder = builder || new_builder
|
49
|
+
|
50
|
+
xml_attrs = default_xml_attributes.merge(:column => column)
|
51
|
+
xml_attrs[:levelType] = level_type if level_type.present?
|
52
|
+
xml_attrs[:type] = type.to_s.capitalize if type.present?
|
53
|
+
builder.level(xml_attrs)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ::Rubiks
|
2
|
+
|
3
|
+
class Measure < ::Rubiks::NamedObject
|
4
|
+
def column(new_name=nil, options={})
|
5
|
+
@column = new_name.to_s if new_name.present?
|
6
|
+
@column ||= @options[:column] || name
|
7
|
+
end
|
8
|
+
|
9
|
+
def aggregator(new_name=nil, options={})
|
10
|
+
@aggregator = new_name.to_s if new_name.present?
|
11
|
+
@aggregator ||= @options[:aggregator] || 'count'
|
12
|
+
end
|
13
|
+
|
14
|
+
def format_string(new_value=nil, options={})
|
15
|
+
@format_string = new_value.to_s if new_value.present?
|
16
|
+
@format_string ||= @options[:format_string]
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_xml(builder = nil)
|
20
|
+
builder = builder || new_builder
|
21
|
+
|
22
|
+
xml_attrs = {:name => caption, :column => column, :aggregator => aggregator}
|
23
|
+
xml_attrs[:formatString] = format_string if format_string.present?
|
24
|
+
builder.measure(xml_attrs)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|