rubiks 0.0.3 → 0.0.4

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.
Files changed (45) hide show
  1. data/.rspec +4 -0
  2. data/.travis.yml +6 -0
  3. data/Gemfile +17 -2
  4. data/Guardfile +4 -4
  5. data/LICENSE.txt +1 -1
  6. data/README.md +9 -4
  7. data/Rakefile +3 -8
  8. data/lib/rubiks/nodes/annotated_node.rb +20 -0
  9. data/lib/rubiks/nodes/cube.rb +77 -0
  10. data/lib/rubiks/nodes/dimension.rb +54 -0
  11. data/lib/rubiks/nodes/hierarchy.rb +55 -0
  12. data/lib/rubiks/nodes/level.rb +29 -0
  13. data/lib/rubiks/nodes/measure.rb +66 -0
  14. data/lib/rubiks/nodes/schema.rb +61 -0
  15. data/lib/rubiks/nodes/validated_node.rb +47 -0
  16. data/lib/rubiks/version.rb +2 -2
  17. data/lib/rubiks.rb +6 -8
  18. data/rubiks.gemspec +5 -13
  19. data/spec/examples/mondrian_xml_example_spec.rb +91 -0
  20. data/spec/rubiks/nodes/annotated_node_spec.rb +24 -0
  21. data/spec/rubiks/nodes/cube_spec.rb +39 -0
  22. data/spec/rubiks/nodes/dimension_spec.rb +26 -0
  23. data/spec/rubiks/nodes/hierarchy_spec.rb +27 -0
  24. data/spec/rubiks/nodes/level_spec.rb +26 -0
  25. data/spec/rubiks/nodes/measure_spec.rb +31 -0
  26. data/spec/rubiks/nodes/schema_spec.rb +59 -0
  27. data/spec/rubiks/nodes/validated_node_spec.rb +49 -0
  28. data/spec/spec_helper.rb +22 -0
  29. data/spec/support/matchers/be_like.rb +24 -0
  30. data/spec/support/schema_context.rb +46 -0
  31. metadata +45 -144
  32. data/.simplecov +0 -6
  33. data/examples/finance/.rvmrc +0 -1
  34. data/examples/finance/Gemfile +0 -11
  35. data/examples/finance/app.rb +0 -14
  36. data/examples/finance/database.yml +0 -5
  37. data/examples/finance/domain.rb +0 -44
  38. data/examples/finance/setup +0 -46
  39. data/lib/rubiks/cube.rb +0 -95
  40. data/lib/rubiks/dimension.rb +0 -23
  41. data/lib/rubiks/hierarchy.rb +0 -15
  42. data/lib/rubiks/transformers/lookup_transformer.rb +0 -101
  43. data/test/rubiks/test_cube.rb +0 -15
  44. data/test/rubiks/test_dimension.rb +0 -11
  45. data/test/test_helper.rb +0 -6
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --order rand
2
+ --colour
3
+ --tty
4
+ --require rspec/pride --format RSpec::Pride
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ bundler_args: --without development
3
+ rvm:
4
+ - '1.9.2'
5
+ notifications:
6
+ email: false
data/Gemfile CHANGED
@@ -1,4 +1,19 @@
1
- source 'https://rubygems.org'
1
+ source 'http://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in rubiks.gemspec
3
+ # rubiks.gemspec defines the runtime dependencies
4
4
  gemspec
5
+
6
+ # Test and development dependencies are defined here
7
+ # so CI can include just test dependencies
8
+ group :test do
9
+ gem 'rake'
10
+ gem 'rspec'
11
+ gem 'rspec-pride'
12
+ end
13
+
14
+ group :development do
15
+ gem 'awesome_print'
16
+ gem 'pry'
17
+ gem 'pry-nav'
18
+ gem 'simplecov'
19
+ end
data/Guardfile CHANGED
@@ -1,5 +1,5 @@
1
- guard 'minitest' do
2
- watch(%r|^test/(.*)\/?test_(.*)\.rb|)
3
- watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
4
- watch(%r|^test/test_helper\.rb|) { "test" }
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
5
  end
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2012 MoneyDesktop Inc.
1
+ Copyright 2013 MoneyDesktop Inc.
2
2
  Copyright Rubiks contributors https://github.com/moneydesktop/rubiks/contributors
3
3
 
4
4
  MIT License
data/README.md CHANGED
@@ -1,13 +1,18 @@
1
1
  # Rubiks
2
2
 
3
- A Ruby OLAP Cube layer.
3
+ [![Gem Version](https://badge.fury.io/rb/rubiks.png)](http://badge.fury.io/rb/rubiks)
4
+ [![Build Status](https://secure.travis-ci.org/moneydesktop/rubiks.png?branch=master)](https://travis-ci.org/moneydesktop/rubiks)
5
+ [![Code Climate](https://codeclimate.com/github/moneydesktop/rubiks.png)](https://codeclimate.com/github/moneydesktop/rubiks)
4
6
 
5
- ## Usage
7
+ Rubiks is a Ruby gem that defines an OLAP schema with `#to_xml` to generate a Mondrian XML schema and `#to_json` for everything else.
6
8
 
7
- Add this line to your application's Gemfile:
9
+ ## Installation
8
10
 
9
- gem 'rubiks'
11
+ Run `gem install rubiks` to install the gem on its own.
12
+
13
+ Or you can add the following to your Gemfile and run the `bundle` command to install it.
10
14
 
15
+ gem 'rubiks'
11
16
 
12
17
  ## Contributing
13
18
 
data/Rakefile CHANGED
@@ -1,10 +1,5 @@
1
- require 'bundler/gem_tasks'
2
- require 'rake'
3
- require 'rake/testtask'
1
+ require 'rspec/core/rake_task'
4
2
 
5
- Rake::TestTask.new do |t|
6
- t.pattern = 'test/**/test_*.rb'
7
- t.libs.push 'test'
8
- end
3
+ RSpec::Core::RakeTask.new(:spec)
9
4
 
10
- task :default => :test
5
+ task :default => :spec
@@ -0,0 +1,20 @@
1
+ require 'rubiks/nodes/validated_node'
2
+
3
+ module ::Rubiks
4
+ class AnnotatedNode < ::Rubiks::ValidatedNode
5
+ value :name, String
6
+
7
+ validates :name_present
8
+
9
+ def name_present
10
+ errors << "Name required on #{self.class.name.split('::').last}" if self.name.blank?
11
+ end
12
+
13
+ def parse_name(name_value)
14
+ return if name_value.nil?
15
+
16
+ self.name = name_value.to_s
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,77 @@
1
+ require 'rubiks/nodes/annotated_node'
2
+ require 'rubiks/nodes/dimension'
3
+ require 'rubiks/nodes/measure'
4
+
5
+ module ::Rubiks
6
+
7
+ class Cube < ::Rubiks::AnnotatedNode
8
+ child :dimensions, [::Rubiks::Dimension]
9
+ child :measures, [::Rubiks::Measure]
10
+
11
+ validates :dimensions_present, :measures_present
12
+
13
+ def self.new_from_hash(hash={})
14
+ new_instance = new('',[],[])
15
+ return new_instance.from_hash(hash)
16
+ end
17
+
18
+ def from_hash(working_hash)
19
+ return self if working_hash.nil?
20
+ working_hash.stringify_keys!
21
+
22
+ parse_name(working_hash.delete('name'))
23
+ parse_dimensions(working_hash.delete('dimensions'))
24
+ parse_measures(working_hash.delete('measures'))
25
+ return self
26
+ end
27
+
28
+ def measures_present
29
+ if self.measures.present?
30
+ self.measures.each do |measure|
31
+ measure.validate
32
+ errors.push(*measure.errors)
33
+ end
34
+ else
35
+ errors << 'Measures Required for Cube'
36
+ end
37
+ end
38
+
39
+ def parse_measures(measures_array)
40
+ return if measures_array.nil? || measures_array.empty?
41
+
42
+ measures_array.each do |measure_hash|
43
+ self.measures << ::Rubiks::Measure.new_from_hash(measure_hash)
44
+ end
45
+ end
46
+
47
+ def dimensions_present
48
+ if self.dimensions.present?
49
+ self.dimensions.each do |dimension|
50
+ dimension.validate
51
+ errors.push(*dimension.errors)
52
+ end
53
+ else
54
+ errors << 'Dimensions Required for Cube'
55
+ end
56
+ end
57
+
58
+ def parse_dimensions(dimensions_array)
59
+ return if dimensions_array.nil? || dimensions_array.empty?
60
+
61
+ dimensions_array.each do |dimension_hash|
62
+ self.dimensions << ::Rubiks::Dimension.new_from_hash(dimension_hash)
63
+ end
64
+ end
65
+
66
+ def to_hash
67
+ hash = {}
68
+
69
+ hash['name'] = self.name.to_s if self.name.present?
70
+ hash['dimensions'] = self.dimensions.map(&:to_hash) if self.dimensions.present?
71
+ hash['measures'] = self.measures.map(&:to_hash) if self.measures.present?
72
+
73
+ return hash
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,54 @@
1
+ require 'rubiks/nodes/validated_node'
2
+ require 'rubiks/nodes/hierarchy'
3
+
4
+ module ::Rubiks
5
+
6
+ class Dimension < ::Rubiks::AnnotatedNode
7
+ child :hierarchies, [::Rubiks::Hierarchy]
8
+
9
+ validates :hierarchies_present
10
+
11
+ def self.new_from_hash(hash={})
12
+ new_instance = new('',[])
13
+ return new_instance.from_hash(hash)
14
+ end
15
+
16
+ def hierarchies_present
17
+ if self.hierarchies.present?
18
+ self.hierarchies.each do |hierarchy|
19
+ hierarchy.validate
20
+ errors.push(*hierarchy.errors)
21
+ end
22
+ else
23
+ errors << 'Hierarchies Required for Dimension'
24
+ end
25
+ end
26
+
27
+ def from_hash(working_hash)
28
+ return self if working_hash.nil?
29
+ working_hash.stringify_keys!
30
+
31
+ parse_name(working_hash.delete('name'))
32
+ parse_hierarchies(working_hash.delete('hierarchies'))
33
+ return self
34
+ end
35
+
36
+ def parse_hierarchies(hierarchies_array)
37
+ return if hierarchies_array.nil? || hierarchies_array.empty?
38
+
39
+ hierarchies_array.each do |hierarchy_hash|
40
+ self.hierarchies << ::Rubiks::Hierarchy.new_from_hash(hierarchy_hash)
41
+ end
42
+ end
43
+
44
+ def to_hash
45
+ hash = {}
46
+
47
+ hash['name'] = self.name.to_s if self.name.present?
48
+ hash['hierarchies'] = self.hierarchies.map(&:to_hash) if self.hierarchies.present?
49
+
50
+ return hash
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,55 @@
1
+ require 'rubiks/nodes/annotated_node'
2
+ require 'rubiks/nodes/level'
3
+
4
+ module ::Rubiks
5
+
6
+ class Hierarchy < ::Rubiks::AnnotatedNode
7
+ child :levels, [::Rubiks::Level]
8
+
9
+ validates :levels_present
10
+
11
+ def self.new_from_hash(hash={})
12
+ new_instance = new('',[])
13
+ return new_instance.from_hash(hash)
14
+ end
15
+
16
+ def levels_present
17
+ if self.levels.present?
18
+ self.levels.each do |level|
19
+ level.validate
20
+ errors.push(*level.errors)
21
+ end
22
+ else
23
+ errors << 'Levels Required for Hierarchy'
24
+ end
25
+ end
26
+
27
+ def from_hash(working_hash)
28
+ return self if working_hash.nil?
29
+ working_hash.stringify_keys!
30
+
31
+ parse_name(working_hash.delete('name'))
32
+ parse_levels(working_hash.delete('levels'))
33
+ return self
34
+ end
35
+
36
+ def parse_levels(levels_array)
37
+ return if levels_array.nil? || levels_array.empty?
38
+
39
+ levels_array.each do |level_hash|
40
+ self.levels << ::Rubiks::Level.new_from_hash(level_hash)
41
+ end
42
+ end
43
+
44
+ def to_hash
45
+ hash = {}
46
+
47
+ hash['name'] = self.name.to_s if self.name.present?
48
+ hash['levels'] = self.levels.map(&:to_hash) if self.levels.present?
49
+
50
+ return hash
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,29 @@
1
+ require 'rubiks/nodes/annotated_node'
2
+ require 'rubiks/nodes/hierarchy'
3
+
4
+ module ::Rubiks
5
+
6
+ class Level < ::Rubiks::AnnotatedNode
7
+ def self.new_from_hash(hash={})
8
+ new_instance = new
9
+ return new_instance.from_hash(hash)
10
+ end
11
+
12
+ def from_hash(working_hash)
13
+ return self if working_hash.nil?
14
+ working_hash.stringify_keys!
15
+
16
+ parse_name(working_hash.delete('name'))
17
+ return self
18
+ end
19
+
20
+ def to_hash
21
+ hash = {}
22
+
23
+ hash['name'] = self.name.to_s if self.name.present?
24
+
25
+ return hash
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,66 @@
1
+ require 'rubiks/nodes/validated_node'
2
+
3
+ module ::Rubiks
4
+
5
+ class Measure < ::Rubiks::AnnotatedNode
6
+ value :column, String
7
+ value :aggregator, String
8
+ value :format_string, String
9
+
10
+ validates :column_present, :aggregator_present
11
+
12
+ def self.new_from_hash(hash={})
13
+ new_instance = new
14
+ return new_instance.from_hash(hash)
15
+ end
16
+
17
+ def from_hash(working_hash)
18
+ return self if working_hash.nil?
19
+ working_hash.stringify_keys!
20
+
21
+ parse_name(working_hash.delete('name'))
22
+ parse_column(working_hash.delete('column'))
23
+ parse_aggregator(working_hash.delete('aggregator'))
24
+ parse_format_string(working_hash.delete('format_string'))
25
+ return self
26
+ end
27
+
28
+ def to_hash
29
+ hash = {}
30
+
31
+ hash['name'] = self.name.to_s if self.name.present?
32
+ hash['column'] = self.column.to_s if self.column.present?
33
+ hash['aggregator'] = self.aggregator.to_s if self.aggregator.present?
34
+ hash['format_string'] = self.format_string.to_s if self.format_string.present?
35
+
36
+ return hash
37
+ end
38
+
39
+ def column_present
40
+ errors << 'Column required on Measure' if self.column.blank?
41
+ end
42
+
43
+ def parse_column(column_value)
44
+ return if column_value.nil?
45
+
46
+ self.column = column_value.to_s
47
+ end
48
+
49
+ def aggregator_present
50
+ errors << 'Aggregator required on Measure' if self.aggregator.blank?
51
+ end
52
+
53
+ def parse_aggregator(aggregator_value)
54
+ return if aggregator_value.nil?
55
+
56
+ self.aggregator = aggregator_value.to_s
57
+ end
58
+
59
+ def parse_format_string(format_string_value)
60
+ return if format_string_value.nil?
61
+
62
+ self.format_string = format_string_value.to_s
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,61 @@
1
+ require 'rubiks/nodes/validated_node'
2
+ require 'rubiks/nodes/cube'
3
+ require 'multi_json'
4
+
5
+ module ::Rubiks
6
+
7
+ class Schema < ::Rubiks::ValidatedNode
8
+ child :cubes, [::Rubiks::Cube]
9
+
10
+ validates :cubes_present
11
+
12
+ def self.new_from_hash(hash={})
13
+ new_instance = new([])
14
+ return new_instance.from_hash(hash)
15
+ end
16
+
17
+ def cubes_present
18
+ if self.cubes.present?
19
+ self.cubes.each do |cube|
20
+ cube.validate
21
+ errors.push(*cube.errors)
22
+ end
23
+ else
24
+ errors << 'Cubes Required for Schema'
25
+ end
26
+ end
27
+
28
+ def from_hash(working_hash)
29
+ return self if working_hash.nil?
30
+ working_hash.stringify_keys!
31
+
32
+ parse_cubes(working_hash.delete('cubes'))
33
+ return self
34
+ end
35
+
36
+ def parse_cubes(cubes_array)
37
+ return if cubes_array.nil? || cubes_array.empty?
38
+
39
+ cubes_array.each do |cube_hash|
40
+ self.cubes << ::Rubiks::Cube.new_from_hash(cube_hash)
41
+ end
42
+ end
43
+
44
+ def to_hash
45
+ hash = {}
46
+
47
+ hash['cubes'] = self.cubes.map(&:to_hash) if self.cubes.present?
48
+
49
+ return hash
50
+ end
51
+
52
+ def to_json
53
+ MultiJson.dump(to_hash)
54
+ end
55
+
56
+ def to_xml
57
+ to_hash.to_xml(:root => 'Schema')
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1,47 @@
1
+ require 'rltk'
2
+ require 'rltk/ast'
3
+
4
+ module ::Rubiks
5
+ class ValidatedNode < ::RLTK::ASTNode
6
+
7
+ class << self
8
+ attr_accessor :validators
9
+
10
+ alias_method :validator_methods, :validators
11
+ end
12
+
13
+ def self.validates(*validator_symbols)
14
+ @validators ||= []
15
+ @validators << validator_symbols.flatten
16
+ @validators.flatten!
17
+ @validators.compact!
18
+ @validators.uniq!
19
+
20
+ return @validators
21
+ end
22
+
23
+ def self.inherited(klass)
24
+ super
25
+ klass.validators = self.validators.nil? ?
26
+ [] :
27
+ self.validators.dup
28
+ end
29
+
30
+ def errors
31
+ @errors ||= []
32
+ end
33
+
34
+ def valid?
35
+ validate if errors.empty?
36
+
37
+ return errors.empty?
38
+ end
39
+
40
+ def validate
41
+ self.class.validator_methods.each do |validator_method|
42
+ self.__send__(validator_method) if respond_to?(validator_method)
43
+ end
44
+ end
45
+
46
+ end
47
+ end
@@ -1,3 +1,3 @@
1
- module Rubiks
2
- VERSION = '0.0.3'
1
+ module ::Rubiks
2
+ VERSION = '0.0.4'
3
3
  end
data/lib/rubiks.rb CHANGED
@@ -1,11 +1,9 @@
1
1
  require 'rubiks/version'
2
2
 
3
- module Rubiks
4
- autoload :Cube, 'rubiks/cube'
5
- autoload :Dimension, 'rubiks/dimension'
6
- autoload :Hierarchy, 'rubiks/hierarchy'
3
+ require 'active_support/core_ext/object/blank'
4
+ require 'active_support/core_ext/hash/deep_dup'
5
+ require 'active_support/core_ext/hash/keys'
6
+ require 'active_support/core_ext/hash/conversions'
7
7
 
8
- module Transformers
9
- autoload :LookupTransformer, 'rubiks/transformers/lookup_transformer'
10
- end
11
- end
8
+ nodes_directory = File.expand_path('../rubiks/nodes', __FILE__)
9
+ Dir["#{nodes_directory}/*.rb"].each { |file| require file }
data/rubiks.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |gem|
8
8
  gem.version = Rubiks::VERSION
9
9
  gem.authors = ['JohnnyT']
10
10
  gem.email = ['johnnyt@moneydesktop.com']
11
- gem.description = %q{A Ruby OLAP Cube library}
12
- gem.summary = gem.description
11
+ gem.description = %q{Define an OLAP schema}
12
+ gem.summary = 'Rubiks is a Ruby gem that defines an OLAP schema and can output the schema as XML and JSON.'
13
13
  gem.homepage = 'https://github.com/moneydesktop/rubiks'
14
14
 
15
15
  gem.files = `git ls-files`.split($/)
@@ -17,15 +17,7 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ['lib']
19
19
 
20
- gem.add_dependency 'arel'
21
-
22
- gem.add_development_dependency 'awesome_print'
23
- gem.add_development_dependency 'guard'
24
- gem.add_development_dependency 'guard-minitest'
25
- gem.add_development_dependency 'minitest'
26
- gem.add_development_dependency 'pry'
27
- gem.add_development_dependency 'rake'
28
- gem.add_development_dependency 'rb-fsevent'
29
- gem.add_development_dependency 'simplecov'
30
- gem.add_development_dependency 'simplecov-gem-adapter'
20
+ gem.add_dependency 'rltk'
21
+ gem.add_dependency 'activesupport'
22
+ gem.add_dependency 'builder'
31
23
  end
@@ -0,0 +1,91 @@
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
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ # describe ::Rubiks::AnnotatedNode do
4
+ # # API
5
+ # specify { subject.respond_to?(:from_hash) }
6
+ # specify { subject.respond_to?(:to_hash) }
7
+ #
8
+ # context 'when parsed from a valid hash' do
9
+ # subject { described_class.new.from_hash('name' => 'some_name') }
10
+ #
11
+ # its(:name) { should eq('some_name') }
12
+ #
13
+ # its(:to_hash) { should have_key('name') }
14
+ #
15
+ # it { should be_valid }
16
+ # end
17
+ #
18
+ # context 'when parsed from an invalid (empty) hash' do
19
+ # subject { described_class.new.from_hash({}) }
20
+ #
21
+ # it { should_not be_valid }
22
+ # end
23
+ #
24
+ # end