rubiks 0.0.4 → 0.0.5

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.
@@ -9,6 +9,7 @@ describe ::Rubiks::Cube do
9
9
  specify { subject.respond_to?(:to_hash) }
10
10
  specify { subject.respond_to?(:dimensions) }
11
11
  specify { subject.respond_to?(:measures) }
12
+ specify { subject.respond_to?(:calculated_members) }
12
13
 
13
14
  context 'when parsed from a valid hash' do
14
15
  subject { described_class.new_from_hash(cube_hash) }
@@ -17,23 +18,46 @@ describe ::Rubiks::Cube do
17
18
 
18
19
  its(:to_hash) { should have_key('name') }
19
20
 
20
- it 'has a Rubiks::Dimension' do
21
- subject.dimensions.first.should be_kind_of(::Rubiks::Dimension)
21
+ describe '#to_xml' do
22
+ it 'renders a cube tag with attributes' do
23
+ subject.to_xml.should include(%Q!<cube name="Fake Cube">!)
24
+ end
22
25
  end
26
+ end
23
27
 
24
- it 'has a Rubiks::Measure' do
25
- subject.measures.first.should be_kind_of(::Rubiks::Measure)
26
- end
28
+ context 'when parsed with date_dimension' do
29
+ subject { described_class.new_from_hash({'date_dimension' => 'Date'}) }
30
+ its(:to_hash) { should have_key('date_dimension') }
31
+ end
27
32
 
28
- it 'has one value' do
29
- subject.values.size.should eq(1)
30
- end
33
+ context 'when parsed with person_dimension' do
34
+ subject { described_class.new_from_hash({'person_dimension' => 'Date'}) }
35
+ its(:to_hash) { should have_key('person_dimension') }
36
+ end
37
+
38
+ context 'when parsed with count_measure' do
39
+ subject { described_class.new_from_hash({'count_measure' => 'Count'}) }
40
+ its(:to_hash) { should have_key('count_measure') }
41
+ end
42
+
43
+ context 'when parsed with person_count_measure' do
44
+ subject { described_class.new_from_hash({'person_count_measure' => 'Count'}) }
45
+ its(:to_hash) { should have_key('person_count_measure') }
31
46
  end
32
47
 
33
48
  context 'when parsed from an invalid (empty) hash' do
34
49
  subject { described_class.new_from_hash({}) }
35
50
 
36
51
  it { should_not be_valid }
52
+
53
+ describe '#to_xml' do
54
+ it 'renders a dimension tag' do
55
+ subject.to_xml.should be_like <<-XML
56
+ <cube>
57
+ </cube>
58
+ XML
59
+ end
60
+ end
37
61
  end
38
62
 
39
63
  end
@@ -15,12 +15,27 @@ describe ::Rubiks::Dimension do
15
15
  its(:to_hash) { should have_key('hierarchies') }
16
16
 
17
17
  it { should be_valid }
18
+
19
+ describe '#to_xml' do
20
+ it 'renders a dimension tag with attributes' do
21
+ subject.to_xml.should include(%Q!<dimension name="Fake Dimension" foreignKey="fake_dimension_id">!)
22
+ end
23
+ end
18
24
  end
19
25
 
20
26
  context 'when parsed from an invalid (empty) hash' do
21
27
  subject { described_class.new_from_hash({}) }
22
28
 
23
29
  it { should_not be_valid }
30
+
31
+ describe '#to_xml' do
32
+ it 'renders a dimension tag' do
33
+ subject.to_xml.should be_like <<-XML
34
+ <dimension>
35
+ </dimension>
36
+ XML
37
+ end
38
+ end
24
39
  end
25
40
 
26
41
  end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- # Mondrian level has: has_all, all_member_name, primary_key
3
2
 
4
3
  describe ::Rubiks::Hierarchy do
5
4
  include_context 'schema_context'
@@ -14,14 +13,36 @@ describe ::Rubiks::Hierarchy do
14
13
  subject { described_class.new_from_hash(hierarchy_hash) }
15
14
 
16
15
  its(:to_hash) { should have_key('levels') }
16
+ its(:to_hash) { should have_key('name') }
17
+ its(:to_hash) { should have_key('dimension') }
17
18
 
18
19
  it { should be_valid }
20
+
21
+ describe '#to_xml' do
22
+ it 'renders a hierarchy tag with attributes' do
23
+ subject.to_xml.should include(%Q!<hierarchy name="Fake Hierarchy" primaryKey="id" hasAll="true">!)
24
+ end
25
+
26
+ it 'renders a table tag with attributes' do
27
+ subject.to_xml.should include(%Q!<table name="view_fake_dimensions"/>!)
28
+ end
29
+ end
19
30
  end
20
31
 
21
32
  context 'when parsed from an invalid (empty) hash' do
22
33
  subject { described_class.new_from_hash({}) }
23
34
 
24
35
  it { should_not be_valid }
36
+
37
+ describe '#to_xml' do
38
+ it 'renders a hierarchy and table tag' do
39
+ subject.to_xml.should be_like <<-XML
40
+ <hierarchy primaryKey="id" hasAll="true">
41
+ <table/>
42
+ </hierarchy>
43
+ XML
44
+ end
45
+ end
25
46
  end
26
47
 
27
48
  end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- # Mondrian level has: unique_members, column, type, name_column, ordinal_column
3
2
 
4
3
  describe ::Rubiks::Level do
5
4
  include_context 'schema_context'
@@ -13,14 +12,82 @@ describe ::Rubiks::Level do
13
12
  subject { described_class.new_from_hash(level_hash) }
14
13
 
15
14
  its(:to_hash) { should have_key('name') }
15
+ its(:to_hash) { should have_key('data_type') }
16
+ its(:to_hash) { should have_key('cardinality') }
17
+ its(:to_hash) { should have_key('contiguous') }
16
18
 
17
19
  it { should be_valid }
20
+
21
+ describe '#to_json' do
22
+ it 'includes the cardinality' do
23
+ subject.to_json.should include('cardinality')
24
+ end
25
+ end
26
+
27
+ describe '#to_xml' do
28
+ it 'does not include the cardinality' do
29
+ subject.to_xml.should_not include('cardinality')
30
+ end
31
+
32
+ it 'includes the type' do
33
+ subject.to_xml.should include('type="Numeric"')
34
+ end
35
+
36
+ it 'renders a level tag with attributes' do
37
+ subject.to_xml.should be_like <<-XML
38
+ <level name="Fake Level" column="fake_level" type="Numeric"/>
39
+ XML
40
+ end
41
+ end
42
+ end
43
+
44
+ context 'when parsed with true sort value' do
45
+ subject { described_class.new_from_hash({'sort' => true}) }
46
+
47
+ describe '#to_xml' do
48
+ it 'has a ordinalColumn' do
49
+ subject.to_xml.should include('ordinalColumn')
50
+ end
51
+ end
52
+ end
53
+
54
+ context 'when parsed with sort column' do
55
+ subject { described_class.new_from_hash({'sort' => 'fake_level_sort'}) }
56
+
57
+ describe '#to_xml' do
58
+ it 'has a ordinalColumn' do
59
+ subject.to_xml.should include('ordinalColumn')
60
+ end
61
+ end
18
62
  end
19
63
 
20
64
  context 'when parsed from an invalid (empty) hash' do
21
65
  subject { described_class.new_from_hash({}) }
22
66
 
23
67
  it { should_not be_valid }
68
+
69
+ describe '#to_xml' do
70
+ it 'renders a level tag' do
71
+ subject.to_xml.should be_like <<-XML
72
+ <level/>
73
+ XML
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'when parsed with an invalid cardinality' do
79
+ subject { described_class.new_from_hash({'cardinality' => 'foo'}) }
80
+ it { should_not be_valid }
81
+ end
82
+
83
+ context 'when parsed with an invalid contiguous value' do
84
+ subject { described_class.new_from_hash({'contiguous' => 'foo'}) }
85
+ it { should_not be_valid }
86
+ end
87
+
88
+ context 'when parsed with an invalid data_type' do
89
+ subject { described_class.new_from_hash({'data_type' => 'foo'}) }
90
+ it { should_not be_valid }
24
91
  end
25
92
 
26
93
  end
@@ -7,9 +7,6 @@ describe ::Rubiks::Measure do
7
7
 
8
8
  specify { subject.respond_to?(:from_hash) }
9
9
  specify { subject.respond_to?(:to_hash) }
10
- specify { subject.respond_to?(:column) }
11
- specify { subject.respond_to?(:aggregator) }
12
- specify { subject.respond_to?(:format_string) }
13
10
 
14
11
  context 'when parsed from a valid hash' do
15
12
  subject { described_class.new_from_hash(measure_hash) }
@@ -17,15 +14,42 @@ describe ::Rubiks::Measure do
17
14
  it { should be_valid }
18
15
 
19
16
  its(:to_hash) { should have_key('name') }
20
- its(:to_hash) { should have_key('column') }
21
17
  its(:to_hash) { should have_key('aggregator') }
22
18
  its(:to_hash) { should have_key('format_string') }
19
+
20
+ describe '#to_xml' do
21
+ it 'renders a measure tag with attributes' do
22
+ subject.to_xml.should be_like <<-XML
23
+ <measure name="Fake Measure" aggregator="sum" formatString="#{subject.format_string}" column="fake_measure"/>
24
+ XML
25
+ end
26
+ end
27
+ end
28
+
29
+ context 'when parsed with a specific column' do
30
+ #subject { described_class.new_from_hash(measure_hash.merge('column' => 'foo')) }
31
+ subject { described_class.new_from_hash('column' => 'foo') }
32
+
33
+ describe '#to_xml' do
34
+ it 'includes the specific column' do
35
+ subject.to_xml.should be_like <<-XML
36
+ <measure column="foo"/>
37
+ XML
38
+ end
39
+ end
23
40
  end
24
41
 
25
42
  context 'when parsed from an invalid (empty) hash' do
26
43
  subject { described_class.new_from_hash({}) }
27
44
 
28
45
  it { should_not be_valid }
29
- end
30
46
 
47
+ describe '#to_xml' do
48
+ it 'renders a measure tag' do
49
+ subject.to_xml.should be_like <<-XML
50
+ <measure/>
51
+ XML
52
+ end
53
+ end
54
+ end
31
55
  end
@@ -17,18 +17,6 @@ describe ::Rubiks::Schema do
17
17
  it { should be_valid }
18
18
 
19
19
  its(:to_hash) { should have_key('cubes') }
20
-
21
- it 'has a cube' do
22
- subject.cubes.length.should eq 1
23
- end
24
-
25
- it 'has a Rubiks::Cube' do
26
- subject.cubes.first.should be_kind_of(::Rubiks::Cube)
27
- end
28
-
29
- it 'has no values' do
30
- subject.values.should eq([])
31
- end
32
20
  end
33
21
 
34
22
  context 'when parsed from an invalid (empty) hash' do
@@ -40,20 +28,11 @@ describe ::Rubiks::Schema do
40
28
  it 'renders XML' do
41
29
  subject.to_xml.should be_like <<-XML
42
30
  <?xml version="1.0" encoding="UTF-8"?>
43
- <Schema>
44
- </Schema>
31
+ <schema name="default">
32
+ </schema>
45
33
  XML
46
34
  end
47
35
  end
48
-
49
- describe '#to_json' do
50
- it 'renders JSON' do
51
- subject.to_json.should be_like <<-JSON
52
- {}
53
- JSON
54
- end
55
- end
56
-
57
36
  end
58
37
 
59
38
  end
data/spec/spec_helper.rb CHANGED
@@ -1,18 +1,37 @@
1
- lib_path = File.expand_path("../../lib", __FILE__)
2
- $LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
1
+ #lib_path = File.expand_path("../../lib", __FILE__)
2
+ #$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
3
+ #
4
+ ## Don't use simplecov in ruby 1.8
5
+ #if RUBY_VERSION !~ /^1\.8/
6
+ # begin
7
+ # require 'simplecov'
8
+ # SimpleCov.start do
9
+ # add_filter '/spec/'
10
+ # end
11
+ # rescue LoadError
12
+ # end
13
+ #end
14
+ #
15
+ #require 'bundler'
16
+ #Bundler.require(:default, :development, :test)
17
+ #
18
+ #require 'rubiks'
19
+ #
20
+ #RSpec.configure do |config|
21
+ # config.include Matchers
22
+ #end
3
23
 
4
- begin
5
- require 'simplecov'
6
- SimpleCov.start do
7
- add_filter '/spec/'
8
- end
9
- rescue LoadError
10
- end
24
+ require 'simplecov'
25
+ require 'coveralls'
11
26
 
12
- require 'bundler'
13
- Bundler.require(:default, :development, :test)
27
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
28
+ SimpleCov::Formatter::HTMLFormatter,
29
+ Coveralls::SimpleCov::Formatter
30
+ ]
31
+ SimpleCov.start
14
32
 
15
33
  require 'rubiks'
34
+ require 'rspec'
16
35
 
17
36
  require 'support/schema_context'
18
37
  require 'support/matchers/be_like'
@@ -10,7 +10,8 @@ shared_context 'schema_context' do
10
10
  {
11
11
  'name' => 'fake_cube',
12
12
  'dimensions' => [dimension_hash.deep_dup],
13
- 'measures' => [measure_hash.deep_dup]
13
+ 'measures' => [measure_hash.deep_dup],
14
+ 'calculated_members' => [calculated_member_hash.deep_dup]
14
15
  }
15
16
  end
16
17
 
@@ -24,23 +25,35 @@ shared_context 'schema_context' do
24
25
  def hierarchy_hash
25
26
  {
26
27
  'name' => 'fake_hierarchy',
28
+ 'dimension' => 'fake_dimension',
27
29
  'levels' => [level_hash.deep_dup]
28
30
  }
29
31
  end
30
32
 
31
33
  def level_hash
32
34
  {
33
- 'name' => 'fake_level'
35
+ 'name' => 'fake_level',
36
+ 'data_type' => 'numeric',
37
+ 'cardinality' => 'normal',
38
+ 'contiguous' => true
34
39
  }
35
40
  end
36
41
 
37
42
  def measure_hash
38
43
  {
39
44
  'name' => 'fake_measure',
40
- 'column' => 'amount',
41
- 'aggregator' => 'count',
45
+ 'aggregator' => 'sum',
42
46
  'format_string' => '$#,###'
43
47
  }
44
48
  end
45
49
 
50
+ def calculated_member_hash
51
+ {
52
+ 'name' => 'fake_calculated_member',
53
+ 'dimension' => 'fake_dimension',
54
+ 'formula' => 'fake_formula',
55
+ 'format_string' => '$#,##0.00'
56
+ }
57
+ end
58
+
46
59
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubiks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-03 00:00:00.000000000 Z
12
+ date: 2013-04-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rltk
@@ -59,7 +59,8 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
- description: Define an OLAP schema
62
+ description: A gem to allow defining an OLAP schema from a hash and generate an XML
63
+ schema for Mondrian
63
64
  email:
64
65
  - johnnyt@moneydesktop.com
65
66
  executables: []
@@ -68,14 +69,20 @@ extra_rdoc_files: []
68
69
  files:
69
70
  - .gitignore
70
71
  - .rspec
72
+ - .rvmrc
71
73
  - .travis.yml
74
+ - .yardopts
75
+ - CHANGELOG.md
76
+ - CONTRIBUTIG.md
72
77
  - Gemfile
73
- - Guardfile
74
- - LICENSE.txt
78
+ - LICENSE.md
75
79
  - README.md
76
80
  - Rakefile
81
+ - examples/mondrian_docs.yml
77
82
  - lib/rubiks.rb
83
+ - lib/rubiks/examples.rb
78
84
  - lib/rubiks/nodes/annotated_node.rb
85
+ - lib/rubiks/nodes/calculated_member.rb
79
86
  - lib/rubiks/nodes/cube.rb
80
87
  - lib/rubiks/nodes/dimension.rb
81
88
  - lib/rubiks/nodes/hierarchy.rb
@@ -85,8 +92,10 @@ files:
85
92
  - lib/rubiks/nodes/validated_node.rb
86
93
  - lib/rubiks/version.rb
87
94
  - rubiks.gemspec
88
- - spec/examples/mondrian_xml_example_spec.rb
95
+ - spec/examples/mondrian_docs_example_spec.rb
96
+ - spec/examples/simple_mondrian_example_spec.rb
89
97
  - spec/rubiks/nodes/annotated_node_spec.rb
98
+ - spec/rubiks/nodes/calculated_member_spec.rb
90
99
  - spec/rubiks/nodes/cube_spec.rb
91
100
  - spec/rubiks/nodes/dimension_spec.rb
92
101
  - spec/rubiks/nodes/hierarchy_spec.rb
@@ -109,22 +118,29 @@ required_ruby_version: !ruby/object:Gem::Requirement
109
118
  - - ! '>='
110
119
  - !ruby/object:Gem::Version
111
120
  version: '0'
121
+ segments:
122
+ - 0
123
+ hash: 2318273741982470273
112
124
  required_rubygems_version: !ruby/object:Gem::Requirement
113
125
  none: false
114
126
  requirements:
115
127
  - - ! '>='
116
128
  - !ruby/object:Gem::Version
117
129
  version: '0'
130
+ segments:
131
+ - 0
132
+ hash: 2318273741982470273
118
133
  requirements: []
119
134
  rubyforge_project:
120
- rubygems_version: 1.8.24
135
+ rubygems_version: 1.8.25
121
136
  signing_key:
122
137
  specification_version: 3
123
- summary: Rubiks is a Ruby gem that defines an OLAP schema and can output the schema
124
- as XML and JSON.
138
+ summary: A gem to provide translation of OLAP schemas
125
139
  test_files:
126
- - spec/examples/mondrian_xml_example_spec.rb
140
+ - spec/examples/mondrian_docs_example_spec.rb
141
+ - spec/examples/simple_mondrian_example_spec.rb
127
142
  - spec/rubiks/nodes/annotated_node_spec.rb
143
+ - spec/rubiks/nodes/calculated_member_spec.rb
128
144
  - spec/rubiks/nodes/cube_spec.rb
129
145
  - spec/rubiks/nodes/dimension_spec.rb
130
146
  - spec/rubiks/nodes/hierarchy_spec.rb
data/Guardfile DELETED
@@ -1,5 +0,0 @@
1
- guard 'rspec' do
2
- watch(%r{^spec/.+_spec\.rb$})
3
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
- watch('spec/spec_helper.rb') { "spec" }
5
- end
@@ -1,91 +0,0 @@
1
- require 'spec_helper'
2
-
3
- # This example is taken from the Mondrian documentation:
4
- # http://mondrian.pentaho.com/documentation/schema.php#Cubes_and_dimensions
5
- # and then modified to use Rails/Rubiks conventions
6
- #
7
- # We want the output to be:
8
- #
9
- # <Schema>
10
- # <Cube name="Sales">
11
- # <Table name="view_sales"/>
12
- #
13
- # <Dimension name="Gender" foreignKey="customer_id">
14
- # <Hierarchy hasAll="true" allMemberName="All Genders" primaryKey="id">
15
- # <Table name="customers"/>
16
- # <Level name="Gender" column="gender" uniqueMembers="true"/>
17
- # </Hierarchy>
18
- # </Dimension>
19
- #
20
- # <Dimension name="Date" foreignKey="date_id">
21
- # <Hierarchy hasAll="false" primaryKey="id">
22
- # <Table name="view_dates"/>
23
- # <Level name="Year" column="year" type="Numeric" uniqueMembers="true"/>
24
- # <Level name="Quarter" column="quarter" uniqueMembers="false"/>
25
- # <Level name="Month" column="month_of_year" type="Numeric" uniqueMembers="false"/>
26
- # </Hierarchy>
27
- # </Dimension>
28
- #
29
- # <Measure name="Unit Sales" column="unit_sales" aggregator="sum" formatString="#,###"/>
30
- # <Measure name="Store Sales" column="store_sales" aggregator="sum" formatString="#,###.##"/>
31
- # <Measure name="Store Cost" column="store_cost" aggregator="sum" formatString="#,###.00"/>
32
- #
33
- # <CalculatedMember name="Profit" dimension="Measures" formula="[Measures].[Store Sales] - [Measures].[Store Cost]">
34
- # <CalculatedMemberProperty name="FORMAT_STRING" value="$#,##0.00"/>
35
- # </CalculatedMember>
36
- # </Cube>
37
- # </Schema>
38
-
39
- describe 'A basic Mondrian XML Schema' do
40
- let(:described_class) { ::Rubiks::Schema }
41
- let(:schema_hash) {
42
- {
43
- 'cubes' => [{
44
- 'name' => 'sales',
45
- 'measures' => [
46
- {
47
- 'name' => 'unit_sales',
48
- 'aggregator' => 'sum',
49
- 'format_string' => '#,###'
50
- },
51
- {
52
- 'name' => 'store_sales',
53
- 'aggregator' => 'sum',
54
- 'format_string' => '#,###.##'
55
- },
56
- {
57
- 'name' => 'store_cost',
58
- 'aggregator' => 'sum',
59
- 'format_string' => '#,###.00'
60
- }
61
- ],
62
- 'dimensions' => [
63
- {
64
- 'name' => 'date',
65
- 'hierarchies' => [{
66
- 'name' => 'day_of_week',
67
- 'levels' => [{
68
- 'name' => 'day_of_week'
69
- }]
70
- }]
71
- }
72
- ]
73
- }]
74
- }
75
- }
76
-
77
- # subject { described_class.new_from_hash(schema_hash) }
78
-
79
- # describe '#to_json' do
80
- # it 'generates a JSON string' do
81
- # subject.to_json.should be_kind_of String
82
- # end
83
-
84
- # it 'generates a valid JSON string' do
85
- # lambda {
86
- # MultiJson.load(subject.to_json)
87
- # }.should_not raise_error MultiJson::LoadError
88
- # end
89
- # end
90
-
91
- end