rubiks 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|