symbolmatrix 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -7,3 +7,12 @@ gemspec
7
7
  group :test do
8
8
  gem "rake"
9
9
  end
10
+
11
+ group :development do
12
+ gem "guard-rspec"
13
+ gem "guard-cucumber"
14
+ gem "libnotify"
15
+ gem "cucumber"
16
+ gem "pry"
17
+ gem "rb-inotify"
18
+ end
data/Guardfile ADDED
@@ -0,0 +1,39 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :cli => "--color --format doc" do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
8
+ watch('spec/spec_helper.rb') { "spec" }
9
+ # watch('spec/complete_features_helper.rb') { "spec" }
10
+ # watch('spec/plain_symbolmatrix_helper.rb') { "spec" }
11
+
12
+ # Rails example
13
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
14
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
15
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
16
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
17
+ watch('config/routes.rb') { "spec/routing" }
18
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
19
+
20
+ # Capybara features specs
21
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
22
+
23
+ # Turnip features and steps
24
+ watch(%r{^spec/acceptance/(.+)\.feature$})
25
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
26
+ end
27
+
28
+
29
+ #guard 'cucumber', :cli => "-ci" do
30
+ # watch(%r{^features/.+\.feature$})
31
+ # watch(%r{^features/support/.+$}) { 'features' }
32
+ # watch(%r{^features/stepdefs/(.+)\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
33
+ #end
34
+
35
+ guard 'cucumber' do
36
+ watch(%r{^features/.+\.feature$})
37
+ watch(%r{^features/support/.+$}) { 'features' }
38
+ watch(%r{^features/stepdefs/(.+)\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
39
+ end
data/README.md CHANGED
@@ -5,6 +5,8 @@ SymbolMatrix
5
5
 
6
6
  > Strongly inspired in [SymbolTable][symboltable] gem by [Michael Jackson][michael-jackson-home] (thanks a lot!)
7
7
 
8
+ > **New!**: SymbolMatrix now features a serialization syntax from which it can be parsed and to which it can be serialized. I'm calling it SMAS (SymbolMAtris Serialization) and it's loosely inspired in both [rake][rake-link] and [thor][thor-link]'s argument syntax styles. Read more about it in the *SMAS* section downstairs.
9
+
8
10
  **SymbolMatrix** is a simple Ruby Gem that extends `Hash` so that only `Symbol`s can be used as keys. Why? Because it also allows you to query the SymbolMatrix object using the dot syntax and a string key equivalent to the symbol one, making it more Principle of Least Surprise.
9
11
 
10
12
  The showdown:
@@ -25,56 +27,135 @@ m['a'] # => 1
25
27
  m.a # => 1
26
28
  ```
27
29
 
28
- If you are familiar with SymbolTable you may have noticed that, so far, the same functionality is provided in the original gem. SymbolMatrix adds two key features:
30
+ If you are familiar with SymbolTable you may have noticed that, so far, the same functionality is provided in the original gem. SymbolMatrix adds three key features:
29
31
 
30
32
  1. **Recursive convertion to SymbolMatrix**
31
33
 
32
34
  ```ruby
33
35
  require "symbolmatrix"
34
36
 
35
- m = SymbolMatrix.new :quantum => { :nano => "data" }
37
+ m = SymbolMatrix :quantum => { :nano => "data" }
36
38
 
37
39
  m.quatum.nano # => "data"
38
40
  ```
39
41
 
40
- 2. **YAML autoloading**
42
+ 2. **JSON/YAML autoloading**
41
43
 
42
44
  ```ruby
43
45
  require "symbolmatrix"
44
46
 
45
- m = SymbolMatrix.new "quantum: of solace"
47
+ m = SymbolMatrix "quantum: of solace"
46
48
  m.quantum # => "of solace"
47
49
 
48
50
  # Or alternatively
49
- m.from_yaml "quantum: of solace"
51
+ m.from.yaml "quantum: of solace"
50
52
 
51
53
  # Provided a file exists "configuration.yaml" with "database_uri: mysql://root@localhost/database"
52
- m.from_file "configuration.yaml"
54
+ m.from.file "configuration.yaml"
53
55
  m.database_uri # => "mysql://root@localhost/database"
54
56
 
55
57
  # Or simply
56
- m = SymbolMatrix.new "configuration.yaml"
58
+ m = SymbolMatrix "configuration.yaml"
59
+ ```
60
+
61
+ Since all JSON is valid YAML... yey, it works with JSON too!
62
+ ```ruby
63
+ require 'symbolmatrix'
64
+
65
+ data = SymbolMatrix '{"message":"Awesome"}'
66
+ data.message # => 'Awesome'
57
67
  ```
58
68
 
69
+ 3. **Own serialization format for command line**
70
+
71
+ Look the next section
72
+
59
73
  [symboltable]: https://github.com/mjijackson/symboltable
60
74
  [michael-jackson-home]: http://mjijackson.com/
75
+ [rake-link]: https://github.com/jimweirich/rake
76
+ [thor-link]: https://github.com/wycats/thor
77
+
78
+ SMAS: SymbolMatrix Serialization
79
+ --------------------------------
80
+
81
+ The serialization format is designed to serve as an alternative for the command line environment, when multiline (YAML) and special characters (JSON) are not well suited. It's very intuitive and designed to closely resemble the way SymbolMatrix is used within Ruby code. For example:
82
+
83
+ ```ruby
84
+ require 'symbolmatrix'
85
+
86
+ s = SymbolMatrix 'this.serialization:format i.think:rocks!'
87
+
88
+ s.this.serialization # => "format"
89
+ s.i.think # => "rocks!"
90
+
91
+ s.from.serialization 'works.with.numbers:793'
92
+
93
+ s.works.with.numbers # => 793
94
+ ```
95
+
96
+ You can get the serialization from any SymbolMatrix:
97
+
98
+ ```ruby
99
+ require 'symbolmatrix'
100
+
101
+ SymbolMatrix(:where => {
102
+ :is => {
103
+ :paris => "france",
104
+ :roma => "italia"
105
+ }
106
+ ).to.serialization # => 'where.is.paris:france where.is.roma:italia'
107
+ ```
108
+
109
+ > This serialization format is better exploited in the [Empezar Ruby Gem][empezar-link]
110
+
111
+ [empezar-link]: https://github.com/Fetcher/empezar
61
112
 
62
113
  Further details
63
114
  ---------------
64
115
 
65
- ### Recursive `#to_hash` convertion
116
+ ### Recursive `#to.hash` convertion
66
117
 
67
- SymbolMatrix provides the `#to_hash` method that recursively transforms the matrix into a n-dimentional Hash.
118
+ SymbolMatrix provides the `#to.hash` method that recursively transforms the matrix into a n-dimentional Hash.
68
119
 
69
- ### Disabling the YAML discovery
120
+ ### Disabling the extras
70
121
 
71
- If for some reason you don't want this class to use YAML, you can just require `symbolmatrix/symbolmatrix` and the YAML functionality will not be loaded.
122
+ If for some reason you don't want this class to use YAML nor the serialization format SMAS, you can just require `symbolmatrix/symbolmatrix` and those functionalities will not be loaded.
72
123
 
73
124
  ### Exceptions
74
125
 
75
126
  Whenever a key is not found in the SymbolMatrix, a custom `SymbolMatrix::KeyNotDefinedException` will be raised.
76
127
  Similarly, if you attempt to use an inconvertible key (inconvertible to `Symbol`) a `SymbolMatrix::InvalidKeyException` will be raised.
77
128
 
129
+ Changelog for 1.0.0
130
+ -------------------
131
+
132
+ Serialization format aside, there had been some minor changes to the API worth noting:
133
+
134
+ ### Deprecations
135
+
136
+ As of version 1.0.0, Writers and Readers has been added, so now the regular methods `from_yaml`, `from_file` and `to_hash` are deprecated in favor of `from.yaml`, `from.file` and `to.hash`. Please change to the new API is you're working with SymbolMatrix right now.
137
+
138
+ ### `.new` no longer needed
139
+
140
+ `SymbolMatrix :a => 'b'` is now equivalent to `SymbolMatrix.new(:a => 'b')`.
141
+
142
+ SymbolMatrix is mostly about the developers having an easier time with code so I place strong priority in these small changes for comfort.
143
+
144
+ ### `#recursive_merge` available
145
+
146
+ > Note: this is not yet working with any Hash, just SymbolMatrices.
147
+
148
+ Yey! This one was missing quite a while from Ruby Hashes (if you are like me and spend a lot of time dealing with multidimensional hashes).
149
+
150
+ The API is straightforward:
151
+ ```ruby
152
+ sm = SymbolMatrix(:a => { :b => "c" })
153
+ sm.recursive_merge SymbolMatrix(:a => { :c => "d"})
154
+
155
+ sm.a.b # => "c"
156
+ sm.a.c # => "d"
157
+ ```
158
+
78
159
  Installation
79
160
  ------------
80
161
 
@@ -89,6 +170,15 @@ And then execute:
89
170
 
90
171
  bundle install
91
172
 
173
+ ## Known issues
174
+
175
+ - When loading a YAML/JSON document that has an sequence –array– as the root item, SymbolMatrix will crash. This is because SymbolMatrix wasn't intended for arrays, just Hashes, and the recursive conversion from Hash to SymbolMatrix is not working with Arrays.
176
+ - Some keys overlap with method names, so can't be used with the dot syntax. For example, `key`. Just use them with the hash syntax instead :)
177
+
178
+ ## Future
179
+
180
+ - Make SymbolMatrix raise a more relevant error when the file does not exist (something along the lines of "There was an error parsing the YAML string, may be it was a file path and the file does not exist?"). It is possible to increase the chances of detecting properly with a really simple regular expression...
181
+
92
182
  ## Testing
93
183
 
94
184
  RSpec specs are provided to check functionality.
@@ -0,0 +1,26 @@
1
+ Feature: Parsing a SymbolMatrix serialization
2
+ In order to be able to build multidimensional hashes from
3
+ single line contexts, such as terminals
4
+ As a developer
5
+ I want to have a simple way to parse a serialization
6
+
7
+ Scenario: Quite basic structure
8
+ Given "data:datum"
9
+ When I parse it
10
+ Then I should see (serialized in yaml)
11
+ """
12
+ data: datum
13
+ """
14
+
15
+ Scenario: Needlessly complicated
16
+ Given "remote.client.host:fetcher remote.client.path:/ remote.client.port:bridge.fetcher remote.server:8080"
17
+ When I parse it
18
+ Then I should see (serialized in yaml)
19
+ """
20
+ remote:
21
+ client:
22
+ host: fetcher
23
+ path: /
24
+ port: bridge.fetcher
25
+ server: 8080
26
+ """
@@ -0,0 +1,43 @@
1
+ Feature: Serializing a SymbolMatrix
2
+ In order to be able to send SymbolMatrices
3
+ in command line environments
4
+ As a developer
5
+ I want to be able to serialize SymbolMatrices
6
+
7
+ Scenario: Nice SymbolMatrix serialized
8
+ Given the SymbolMatrix:
9
+ """
10
+ roses:
11
+ are: red
12
+ violets:
13
+ are: blue
14
+ I:
15
+ get: joke
16
+ like: poetry
17
+ say:
18
+ to: you
19
+ some: stuff
20
+ """
21
+ When I serialize it
22
+ Then I should get "roses.are:red violets.are:blue I.get:joke I.like:poetry I.say.to:you I.say.some:stuff"
23
+
24
+ Scenario: Serializing and parsing back
25
+ Given the SymbolMatrix:
26
+ """
27
+ greetings:
28
+ aloha: hawaii
29
+ cities:
30
+ roma: italy
31
+ paris: france
32
+ """
33
+ When I serialize it
34
+ Then I should get "greetings.aloha:hawaii cities.roma:italy cities.paris:france"
35
+ When I parse it
36
+ Then I should see (serialized in yaml)
37
+ """
38
+ greetings:
39
+ aloha: hawaii
40
+ cities:
41
+ roma: italy
42
+ paris: france
43
+ """
@@ -0,0 +1,11 @@
1
+ Given /^"(.+?)"$/ do |serialization|
2
+ @serialization = serialization
3
+ end
4
+
5
+ When /^I parse it$/ do
6
+ @parsed = SymbolMatrix.new @serialization
7
+ end
8
+
9
+ Then /^I should see \(serialized in yaml\)$/ do |data|
10
+ @parsed.to_hash.should include SymbolMatrix.new(data).to_hash
11
+ end
@@ -0,0 +1,11 @@
1
+ Given /^the SymbolMatrix:$/ do |yaml|
2
+ @symbolmatrix = SymbolMatrix yaml
3
+ end
4
+
5
+ When /^I serialize it$/ do
6
+ @serialization = @symbolmatrix.to.serialization
7
+ end
8
+
9
+ Then /^I should get "(.+?)"$/ do |serialization|
10
+ @serialization.should == serialization
11
+ end
@@ -0,0 +1,3 @@
1
+ $:.push File.expand_path "../../../lib", __FILE__
2
+
3
+ require 'symbolmatrix'
@@ -0,0 +1,37 @@
1
+ module Reader
2
+ class SymbolMatrix
3
+ attr_accessor :source
4
+
5
+ def initialize source
6
+ @source = source
7
+ end
8
+
9
+ def file path
10
+ @source.merge! YAML.load_file path
11
+ end
12
+
13
+ def yaml data
14
+ @source.merge! YAML.load data
15
+ end
16
+
17
+ def serialization data
18
+ @source.merge! ::SymbolMatrix::Serialization.parse data
19
+ end
20
+
21
+ alias :smas :serialization
22
+ end
23
+ end
24
+
25
+ class SymbolMatrix < Hash
26
+ include Discoverer::Reader
27
+
28
+ # @deprecated Use #from.yaml
29
+ def from_yaml *args
30
+ Kernel.warn "[DEPRECATION]: #from_yaml is deprecated, please use #from.yaml instead"
31
+ end
32
+
33
+ # @deprecated Use #from.file
34
+ def from_file *args
35
+ Kernel.warn "[DEPRECATION]: #from_file is deprecated, please use #from.file instead"
36
+ end
37
+ end
data/lib/symbolmatrix.rb CHANGED
@@ -1,2 +1,7 @@
1
- require "symbolmatrix/symbolmatrix"
2
- require "yaml/symbolmatrix"
1
+ require 'yaml'
2
+ require 'discoverer'
3
+
4
+ require 'symbolmatrix/symbolmatrix'
5
+ require 'symbolmatrix/serialization'
6
+ require 'reader/symbolmatrix'
7
+ require 'writer/symbolmatrix'
@@ -0,0 +1,41 @@
1
+ class SymbolMatrix < Hash
2
+ class Serialization
3
+ def self.parse serialization
4
+ result = SymbolMatrix.new
5
+ if serialization.include? " "
6
+ serialization.split(" ").each do |command|
7
+ result = result.recursive_merge parse command
8
+ end
9
+ else
10
+ parts = serialization.split ":"
11
+ unless parts.first.include? "."
12
+ begin
13
+ parts[1] = Integer parts.last
14
+ rescue ArgumentError => e
15
+ end
16
+ result.merge! parts.first => parts.last
17
+ else
18
+ the_key = serialization[0..serialization.index(".") -1]
19
+ result[the_key] = parse serialization[serialization.index(".")+1..-1]
20
+ end
21
+ end
22
+ result
23
+ end
24
+ end
25
+
26
+ def initialize argument = nil
27
+ if argument.is_a? String
28
+ if File.exist? argument
29
+ from.file argument
30
+ else
31
+ begin
32
+ from.yaml argument
33
+ rescue NoMethodError => e
34
+ from.serialization argument
35
+ end
36
+ end
37
+ else
38
+ merge! argument unless argument.nil?
39
+ end
40
+ end
41
+ end
@@ -36,18 +36,9 @@ class SymbolMatrix < Hash
36
36
 
37
37
  alias []= store
38
38
 
39
- # Returns a hashed version of this SymbolMatrix, with all SymbolMatrix objects within recursively
40
- # converted into hashes
41
- def to_hash recursive = true
42
- the_hash = {}
43
- self.each do |key, value|
44
- if value.is_a? SymbolMatrix and recursive
45
- the_hash[key] = value.to_hash
46
- else
47
- the_hash[key] = value
48
- end
49
- end
50
- return the_hash
39
+ # @deprecated Use #to.hash instead
40
+ def to_hash
41
+ Kernel.warn "[DEPRECATION]: #to_hash is deprecated, please use #to.hash instead"
51
42
  end
52
43
 
53
44
  # Merges the passed hash within self
@@ -77,6 +68,27 @@ class SymbolMatrix < Hash
77
68
  end
78
69
  end
79
70
 
71
+ # Merges this SymbolMatrix with another SymbolMatrix recursively
72
+ def recursive_merge hash
73
+ result = SymbolMatrix.new
74
+ self.keys.each do |key|
75
+ result[key] = self[key]
76
+ end
77
+
78
+ hash.keys.each do |key|
79
+ if result.has_key? key
80
+ result[key] = result[key].recursive_merge hash[key]
81
+ else
82
+ result[key] = hash[key]
83
+ end
84
+ end
85
+ return result
86
+ end
87
+
80
88
  class KeyNotDefinedException < RuntimeError; end
81
89
  class InvalidKeyException < RuntimeError; end
82
90
  end
91
+
92
+ def SymbolMatrix *args
93
+ SymbolMatrix.new *args
94
+ end
@@ -1,3 +1,3 @@
1
1
  module Symbolmatrix
2
- VERSION = "0.0.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,39 @@
1
+ module Writer
2
+ class SymbolMatrix
3
+ attr_accessor :source
4
+
5
+ def initialize source
6
+ @source = source
7
+ end
8
+
9
+ def serialization prefix = nil
10
+ result = ""
11
+ @source.each do |key, value|
12
+ unless value.is_a? Hash
13
+ result += " #{prefix}#{key}:#{value}"
14
+ else
15
+ result += " " + Writer::SymbolMatrix.new(value).serialization("#{prefix}#{key}.")
16
+ end
17
+ end
18
+ result[1..-1]
19
+ end
20
+
21
+ alias :smas :serialization
22
+
23
+ def hash
24
+ the_hash = {}
25
+ @source.each do |key, value|
26
+ if value.respond_to? :to
27
+ the_hash[key] = value.to.hash
28
+ else
29
+ the_hash[key] = value
30
+ end
31
+ end
32
+ the_hash
33
+ end
34
+ end
35
+ end
36
+
37
+ class SymbolMatrix < Hash
38
+ include Discoverer::Writer
39
+ end
@@ -0,0 +1,3 @@
1
+ require "symbolmatrix"
2
+
3
+ require "fast/fast" # For testing easyness
@@ -0,0 +1 @@
1
+ require 'symbolmatrix/symbolmatrix'
@@ -0,0 +1,78 @@
1
+ require 'complete_features_helper'
2
+
3
+ describe Reader::SymbolMatrix do
4
+ describe '#initialize' do
5
+ it 'should receive a source and add it as source' do
6
+ source = stub 'source'
7
+ reader = Reader::SymbolMatrix.new source
8
+ reader.source.should == source
9
+ end
10
+ end
11
+
12
+ describe "#yaml" do
13
+ it "should call #merge! the source using the parsed YAML data as argument" do
14
+ sample_yaml = "a: { nested: { data: with, very: much }, content: to find }"
15
+ the_stub = stub "a theoretical SymbolMatrix"
16
+ reader = Reader::SymbolMatrix.new the_stub
17
+ the_stub.should_receive(:merge!).with "a" => { "nested" => { "data" => "with", "very" => "much" }, "content" => "to find" }
18
+ reader.yaml sample_yaml
19
+ end
20
+ end
21
+
22
+ describe "#file" do
23
+ context "there is a YAML file in the given path" do
24
+ before do
25
+ Fast.file.write "temp/data.yaml", "a: { nested: { data: with, very: much }, content: to find }"
26
+ end
27
+
28
+ it "should call #merge! on the source using the parsed YAML data found in the file" do
29
+ the_stub = stub "a theoretical SymbolMatrix"
30
+ reader = Reader::SymbolMatrix.new the_stub
31
+ the_stub.should_receive(:merge!).with "a" => { "nested" => { "data" => "with", "very" => "much" }, "content" => "to find" }
32
+ reader.file "temp/data.yaml"
33
+ end
34
+
35
+ after do
36
+ Fast.dir.remove! :temp
37
+ end
38
+ end
39
+ end
40
+
41
+ shared_examples_for "any serialization" do
42
+ it 'should call merge! to source with the parsed data' do
43
+ the_sm = stub 'sm'
44
+ data_stub = stub 'data'
45
+ ready_to_merge = stub 'ready to merge'
46
+ reader = Reader::SymbolMatrix.new the_sm
47
+ SymbolMatrix::Serialization.should_receive(:parse).with(data_stub).and_return ready_to_merge
48
+ the_sm.should_receive(:merge!).with ready_to_merge
49
+ reader.send @method, data_stub
50
+ end
51
+ end
52
+
53
+ describe "#serialization" do
54
+ before { @method = :serialization }
55
+ it_behaves_like 'any serialization'
56
+ end
57
+
58
+ describe '#smas' do
59
+ before { @method = :smas }
60
+ it_behaves_like 'any serialization'
61
+ end
62
+ end
63
+
64
+ describe SymbolMatrix do
65
+ it 'should include the Discoverer for Reader' do
66
+ SymbolMatrix.ancestors.should include Discoverer::Reader
67
+ end
68
+
69
+ it 'should feature a deprecation notice in #from_yaml' do
70
+ Kernel.should_receive(:warn).with "[DEPRECATION]: #from_yaml is deprecated, please use #from.yaml instead"
71
+ SymbolMatrix.new.from_yaml stub 'argument'
72
+ end
73
+
74
+ it 'should feature a deprecation notice in #from_file' do
75
+ Kernel.should_receive(:warn).with "[DEPRECATION]: #from_file is deprecated, please use #from.file instead"
76
+ SymbolMatrix.new.from_file stub 'argument'
77
+ end
78
+ end
@@ -0,0 +1,109 @@
1
+ require 'complete_features_helper'
2
+
3
+ describe SymbolMatrix::Serialization do
4
+ describe '.parse' do
5
+ it 'should parse a simple string aja:hola' do
6
+ sm = SymbolMatrix::Serialization.parse 'aja:hola'
7
+ sm.aja.should == 'hola'
8
+ end
9
+
10
+ it 'should parse another simple string esto:distinto' do
11
+ SymbolMatrix::Serialization
12
+ .parse('esto:distinto')
13
+ .esto.should == "distinto"
14
+ end
15
+
16
+ it 'should parse to a number when is a number' do
17
+ SymbolMatrix::Serialization
18
+ .parse("esto:3442")
19
+ .esto.should == 3442
20
+ end
21
+
22
+ it 'should parse a more complex string' do
23
+ sm = SymbolMatrix::Serialization.parse 'hola:eso que:pensas'
24
+ sm.hola.should == 'eso'
25
+ sm.que.should == 'pensas'
26
+ end
27
+
28
+ it 'should parse another complex string' do
29
+ sm = SymbolMatrix::Serialization
30
+ .parse("esto:es bastante:original gracias:bdd")
31
+ sm.esto.should == "es"
32
+ sm.bastante.should == "original"
33
+ sm.gracias.should == "bdd"
34
+ end
35
+
36
+ it 'should parse a string with a single dot' do
37
+ SymbolMatrix::Serialization
38
+ .parse("just.one:dot")
39
+ .just.one.should == "dot"
40
+ end
41
+
42
+ it 'should parse another string with single dot' do
43
+ SymbolMatrix::Serialization
44
+ .parse("just.one:point")
45
+ .just.one.should == "point"
46
+ end
47
+
48
+ it 'should parse another one, other var name' do
49
+ SymbolMatrix::Serialization
50
+ .parse("just.another:data")
51
+ .just.another.should == "data"
52
+ end
53
+
54
+ it 'should parse a string with dots' do
55
+ SymbolMatrix::Serialization
56
+ .parse("the.one.with:dots")
57
+ .the.one.with.should == "dots"
58
+ end
59
+
60
+ it 'should parse a string with dots and spaces' do
61
+ sm = SymbolMatrix::Serialization
62
+ .parse("in.one.with:dots the.other.with:dots")
63
+ sm.the.other.with.should == "dots"
64
+ sm.in.one.with.should == "dots"
65
+ end
66
+
67
+ it 'should merge recursively when needed' do
68
+ sm = SymbolMatrix::Serialization
69
+ .parse("client.host:localhost client.path:hola")
70
+
71
+ sm.client.host.should == "localhost"
72
+ sm.client.path.should == "hola"
73
+ end
74
+ end
75
+ end
76
+
77
+ describe SymbolMatrix do
78
+ describe "#initialize" do
79
+ context "a valid path to a file is provided" do
80
+ before do
81
+ Fast.file.write "temp/data.yaml", "a: { nested: { data: with, very: much }, content: to find }"
82
+ end
83
+
84
+ it "should load the data into self" do
85
+ f = SymbolMatrix.new "temp/data.yaml"
86
+ f.a.nested.data.should == "with"
87
+ end
88
+
89
+ after do
90
+ Fast.dir.remove! :temp
91
+ end
92
+ end
93
+
94
+ context "a YAML string is provided" do
95
+ it "should load the data into self" do
96
+ e = SymbolMatrix.new "beta: { nano: { data: with, very: much }, content: to find }"
97
+ e.beta.nano[:very].should == "much"
98
+ end
99
+ end
100
+
101
+ context "a SymbolMatrix serialization is provided" do
102
+ it 'should load the data into self' do
103
+ a = SymbolMatrix.new "those.pesky:attempts of.making.it:work"
104
+ a.those.pesky.should == "attempts"
105
+ a.of.making.it.should == "work"
106
+ end
107
+ end
108
+ end
109
+ end
@@ -1,7 +1,6 @@
1
- require "symbolmatrix/symbolmatrix"
1
+ require "plain_symbolmatrix_helper"
2
2
 
3
3
  describe SymbolMatrix do
4
-
5
4
  describe "#validate_key" do
6
5
  context "an not convertible to Symbol key is passed" do
7
6
  it "should raise a SymbolMatrix::InvalidKeyException" do
@@ -76,34 +75,9 @@ describe SymbolMatrix do
76
75
  end
77
76
 
78
77
  describe "#to_hash" do
79
- it "should return an instance of Hash" do
80
- m = SymbolMatrix[:b, 1]
81
- m.to_hash.should be_instance_of Hash
82
- end
83
-
84
- it "should have the same keys" do
85
- m = SymbolMatrix[:a, 1]
86
- m.to_hash[:a].should == 1
87
- end
88
-
89
- context "there is some SymbolMatrix within this SymbolMatrix" do
90
- it "should recursively call #to_hash in it" do
91
- inside = SymbolMatrix.new
92
- inside.should_receive :to_hash
93
-
94
- m = SymbolMatrix[:a, inside]
95
- m.to_hash
96
- end
97
-
98
- context "and recursive is set to false" do
99
- it "should not call #to_hash on values" do
100
- inside = SymbolMatrix.new
101
- inside.should_not_receive :to_hash
102
-
103
- m = SymbolMatrix[:a, inside]
104
- m.to_hash false
105
- end
106
- end
78
+ it "should show a deprecation notice" do
79
+ Kernel.should_receive(:warn).with "[DEPRECATION]: #to_hash is deprecated, please use #to.hash instead"
80
+ SymbolMatrix.new.to_hash
107
81
  end
108
82
  end
109
83
 
@@ -144,4 +118,61 @@ describe SymbolMatrix do
144
118
  a.a.should be_instance_of B
145
119
  end
146
120
  end
121
+
122
+ describe "#recursive_merge" do
123
+ it 'should merge two symbolmatrices' do
124
+ sm = SymbolMatrix.new a: "hola"
125
+ result = sm.recursive_merge SymbolMatrix.new b: "chau"
126
+ result.a.should == "hola"
127
+ result.b.should == "chau"
128
+ end
129
+
130
+ it 'should merge two symbolmatrices (new values)' do
131
+ sm = SymbolMatrix.new a: "hey"
132
+ result = sm.recursive_merge SymbolMatrix.new b: "bye"
133
+ result.a.should == "hey"
134
+ result.b.should == "bye"
135
+ end
136
+
137
+ it 'should merge two symbolmatrices (new keys)' do
138
+ sm = SymbolMatrix.new y: "allo"
139
+ result = sm.recursive_merge SymbolMatrix.new z: "ciao"
140
+ result.y.should == "allo"
141
+ result.z.should == "ciao"
142
+ end
143
+
144
+ it 'should recursively merge this with that (simple)' do
145
+ sm = SymbolMatrix.new another: { b: "aa" }
146
+ result = sm.recursive_merge SymbolMatrix.new another: { c: "ee" }
147
+ result.another.b.should == "aa"
148
+ result.another.c.should == "ee"
149
+ end
150
+
151
+ it 'should recursively merge this with that (simple)' do
152
+ sm = SymbolMatrix.new distinct: { b: "rr" }
153
+ result = sm.recursive_merge SymbolMatrix.new distinct: { c: "gg" }
154
+ result.distinct.b.should == "rr"
155
+ result.distinct.c.should == "gg"
156
+ end
157
+
158
+ it 'should recursively merge this with that v2 (simple)' do
159
+ sm = SymbolMatrix.new a: { z: "ee" }
160
+ result = sm.recursive_merge SymbolMatrix.new a: { g: "oo" }
161
+ result.a.z.should == "ee"
162
+ result.a.g.should == "oo"
163
+ end
164
+
165
+ it 'should recursively merge this with the argument hash' do
166
+ sm = SymbolMatrix.new a: { b: { c: "hola" } }
167
+ result = sm.recursive_merge a: { b: { d: "aaa" } }
168
+ result.a.b.c.should == "hola"
169
+ result.a.b.d.should == "aaa"
170
+ end
171
+ end
172
+
173
+ it 'should be a method that calls SymbolMatrix.new with its arguments' do
174
+ argument = stub 'argument'
175
+ SymbolMatrix.should_receive(:new).with argument
176
+ SymbolMatrix argument
177
+ end
147
178
  end
@@ -0,0 +1,155 @@
1
+ require 'complete_features_helper'
2
+
3
+ describe Writer::SymbolMatrix do
4
+ describe '#initialize' do
5
+ it 'should set the argument as the source' do
6
+ source = stub 'source'
7
+ writer = Writer::SymbolMatrix.new source
8
+ writer.source.should == source
9
+ end
10
+ end
11
+
12
+ describe '#hash' do
13
+ it "should return an instance of Hash" do
14
+ m = SymbolMatrix[:b, 1]
15
+ writer = Writer::SymbolMatrix.new m
16
+ writer.hash.should be_instance_of Hash
17
+ end
18
+
19
+ it "should have the same keys" do
20
+ m = SymbolMatrix[:a, 1]
21
+ writer = Writer::SymbolMatrix.new m
22
+ writer.hash[:a].should == 1
23
+ end
24
+
25
+ it "should have the same keys (more keys)" do
26
+ m = SymbolMatrix[:a, 2]
27
+ writer = Writer::SymbolMatrix.new m
28
+ writer.hash[:a].should == 2
29
+ end
30
+
31
+ context "there is some SymbolMatrix within this SymbolMatrix" do
32
+ it "should recursively call #to.hash in it" do
33
+ in_writer = stub 'inside writer'
34
+
35
+ inside = SymbolMatrix.new
36
+ inside.should_receive(:to).and_return in_writer
37
+ in_writer.should_receive(:hash)
38
+
39
+ m = SymbolMatrix[:a, inside]
40
+ writer = Writer::SymbolMatrix.new m
41
+ writer.hash
42
+ end
43
+ end
44
+ end
45
+
46
+ shared_examples_for 'any serialization' do
47
+ it 'should serialize "try: this" into "try:this"' do
48
+ s = SymbolMatrix try: "this"
49
+ writer = Writer::SymbolMatrix.new s
50
+ writer.send(@method).should == "try:this"
51
+ end
52
+
53
+ it 'should serialize "try: that" into "try:that"' do
54
+ s = SymbolMatrix try: "that"
55
+ Writer::SymbolMatrix
56
+ .new(s).send(@method).should == "try:that"
57
+ end
58
+
59
+ it 'should serialize "attempt: this" into "attempt:this"' do
60
+ Writer::SymbolMatrix
61
+ .new(SymbolMatrix(attempt: "this"))
62
+ .send(@method).should == "attempt:this"
63
+ end
64
+
65
+ it 'should serialize "attempt: that" into "attempt:that"' do
66
+ Writer::SymbolMatrix
67
+ .new(SymbolMatrix(attempt: "that"))
68
+ .send(@method).should == "attempt:that"
69
+ end
70
+
71
+ it 'should serialize a more complex hash' do
72
+ Writer::SymbolMatrix
73
+ .new(SymbolMatrix(a: "b", c: "d"))
74
+ .send(@method).should == "a:b c:d"
75
+ end
76
+
77
+ it 'should serialize a more complex hash with different values' do
78
+ Writer::SymbolMatrix
79
+ .new(SymbolMatrix(g: "e", r: "t"))
80
+ .send(@method).should == "g:e r:t"
81
+ end
82
+
83
+ it 'should serialize a multidimentional hash' do
84
+ Writer::SymbolMatrix
85
+ .new(SymbolMatrix(g: {e: "s"}))
86
+ .send(@method).should == "g.e:s"
87
+ end
88
+
89
+ it 'should serialize a different multidimentional hash' do
90
+ Writer::SymbolMatrix
91
+ .new(SymbolMatrix(r: {e: "s"}))
92
+ .send(@method).should == "r.e:s"
93
+ end
94
+
95
+ it 'should serialize a yet different multidimentional hash' do
96
+ Writer::SymbolMatrix
97
+ .new(SymbolMatrix(r: {a: "s"}))
98
+ .send(@method).should == "r.a:s"
99
+ end
100
+
101
+ it 'should serialize a more complex multidimentional hash' do
102
+ Writer::SymbolMatrix
103
+ .new(SymbolMatrix(r: {a: "s", f: "o"}))
104
+ .send(@method).should == "r.a:s r.f:o"
105
+ end
106
+
107
+ it 'should serialize a different more complex multidimentional hash' do
108
+ Writer::SymbolMatrix
109
+ .new(SymbolMatrix(r: {ar: "s", fe: "o"}))
110
+ .send(@method).should == "r.ar:s r.fe:o"
111
+ end
112
+
113
+ it 'should serialize a yet different more complex multidimentional hash' do
114
+ Writer::SymbolMatrix
115
+ .new(SymbolMatrix(r: {ar: "s", fe: "o", wh: "at"}))
116
+ .send(@method).should == "r.ar:s r.fe:o r.wh:at"
117
+ end
118
+
119
+ it 'should serialize a more complex multidimentional hash' do
120
+ Writer::SymbolMatrix
121
+ .new(SymbolMatrix(r: {a: { f: "o", s: "h", y: "u"}}))
122
+ .send(@method).should == "r.a.f:o r.a.s:h r.a.y:u"
123
+ end
124
+
125
+ it 'should transform the multidimentional hash into a simple dot and colons serialization' do
126
+ multidimentional = SymbolMatrix.new hola: {
127
+ the: "start",
128
+ asdfdf: 8989,
129
+ of: {
130
+ some: "multidimentional"
131
+ }
132
+ },
133
+ stuff: "oops"
134
+
135
+ writer = Writer::SymbolMatrix.new multidimentional
136
+ writer.send(@method).should == "hola.the:start hola.asdfdf:8989 hola.of.some:multidimentional stuff:oops"
137
+ end
138
+ end
139
+
140
+ describe '#serialization' do
141
+ before { @method = :serialization }
142
+ it_behaves_like 'any serialization'
143
+ end
144
+
145
+ describe '#smas' do
146
+ before { @method = :smas }
147
+ it_behaves_like 'any serialization'
148
+ end
149
+ end
150
+
151
+ describe SymbolMatrix do
152
+ it 'should include the Discoverer for Writer' do
153
+ SymbolMatrix.ancestors.should include Discoverer::Writer
154
+ end
155
+ end
data/symbolmatrix.gemspec CHANGED
@@ -8,8 +8,9 @@ Gem::Specification.new do |gem|
8
8
  gem.summary = %q{Very useful for configuration files, SymbolMatrix is a hash-like multidimentional Symbol-only class with ability to discover and load YAML data}
9
9
  gem.homepage = "http://github.com/fetcher/symbolmatrix"
10
10
 
11
+ gem.add_dependency "discoverer"
12
+
11
13
  gem.add_development_dependency "rspec"
12
- gem.add_development_dependency "pry"
13
14
  gem.add_development_dependency "fast"
14
15
 
15
16
  gem.files = `git ls-files`.split($\)
metadata CHANGED
@@ -1,120 +1,132 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: symbolmatrix
3
- version: !ruby/object:Gem::Version
4
- hash: 29
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 1
10
- version: 0.0.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Xavier Via
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-07-31 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- type: :development
22
- requirement: &id001 !ruby/object:Gem::Requirement
12
+ date: 2012-12-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: discoverer
16
+ requirement: !ruby/object:Gem::Requirement
23
17
  none: false
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- hash: 3
28
- segments:
29
- - 0
30
- version: "0"
31
- version_requirements: *id001
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
32
23
  prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
33
31
  name: rspec
34
- - !ruby/object:Gem::Dependency
35
- type: :development
36
- requirement: &id002 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
37
33
  none: false
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- hash: 3
42
- segments:
43
- - 0
44
- version: "0"
45
- version_requirements: *id002
46
- prerelease: false
47
- name: pry
48
- - !ruby/object:Gem::Dependency
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
49
38
  type: :development
50
- requirement: &id003 !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- hash: 3
56
- segments:
57
- - 0
58
- version: "0"
59
- version_requirements: *id003
60
39
  prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
61
47
  name: fast
62
- description: Very useful for configuration files, SymbolMatrix is a hash-like multidimentional Symbol-only class with ability to discover and load YAML data
63
- email:
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Very useful for configuration files, SymbolMatrix is a hash-like multidimentional
63
+ Symbol-only class with ability to discover and load YAML data
64
+ email:
64
65
  - xavier.via.canel@gmail.com
65
66
  executables: []
66
-
67
67
  extensions: []
68
-
69
68
  extra_rdoc_files: []
70
-
71
- files:
69
+ files:
72
70
  - .gitignore
73
71
  - .travis.yml
74
72
  - Gemfile
73
+ - Guardfile
75
74
  - LICENSE
76
75
  - README.md
77
76
  - Rakefile
77
+ - features/parse_serialization.feature
78
+ - features/serialize.feature
79
+ - features/stepdefs/parse_serialization.rb
80
+ - features/stepdefs/serialize.rb
81
+ - features/support/env.rb
82
+ - lib/reader/symbolmatrix.rb
78
83
  - lib/symbolmatrix.rb
84
+ - lib/symbolmatrix/serialization.rb
79
85
  - lib/symbolmatrix/symbolmatrix.rb
80
86
  - lib/symbolmatrix/version.rb
81
- - lib/yaml/symbolmatrix.rb
82
- - spec/symbolmatrix_spec.rb
83
- - spec/yaml-symbolmatrix_spec.rb
87
+ - lib/writer/symbolmatrix.rb
88
+ - spec/complete_features_helper.rb
89
+ - spec/plain_symbolmatrix_helper.rb
90
+ - spec/reader/symbolmatrix_spec.rb
91
+ - spec/symbolmatrix/serialization_spec.rb
92
+ - spec/symbolmatrix/symbolmatrix_spec.rb
93
+ - spec/writer/symbolmatrix_spec.rb
84
94
  - symbolmatrix.gemspec
85
95
  homepage: http://github.com/fetcher/symbolmatrix
86
96
  licenses: []
87
-
88
97
  post_install_message:
89
98
  rdoc_options: []
90
-
91
- require_paths:
99
+ require_paths:
92
100
  - lib
93
- required_ruby_version: !ruby/object:Gem::Requirement
101
+ required_ruby_version: !ruby/object:Gem::Requirement
94
102
  none: false
95
- requirements:
96
- - - ">="
97
- - !ruby/object:Gem::Version
98
- hash: 3
99
- segments:
100
- - 0
101
- version: "0"
102
- required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
108
  none: false
104
- requirements:
105
- - - ">="
106
- - !ruby/object:Gem::Version
107
- hash: 3
108
- segments:
109
- - 0
110
- version: "0"
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
111
113
  requirements: []
112
-
113
114
  rubyforge_project:
114
- rubygems_version: 1.8.24
115
+ rubygems_version: 1.8.21
115
116
  signing_key:
116
117
  specification_version: 3
117
- summary: Very useful for configuration files, SymbolMatrix is a hash-like multidimentional Symbol-only class with ability to discover and load YAML data
118
- test_files:
119
- - spec/symbolmatrix_spec.rb
120
- - spec/yaml-symbolmatrix_spec.rb
118
+ summary: Very useful for configuration files, SymbolMatrix is a hash-like multidimentional
119
+ Symbol-only class with ability to discover and load YAML data
120
+ test_files:
121
+ - features/parse_serialization.feature
122
+ - features/serialize.feature
123
+ - features/stepdefs/parse_serialization.rb
124
+ - features/stepdefs/serialize.rb
125
+ - features/support/env.rb
126
+ - spec/complete_features_helper.rb
127
+ - spec/plain_symbolmatrix_helper.rb
128
+ - spec/reader/symbolmatrix_spec.rb
129
+ - spec/symbolmatrix/serialization_spec.rb
130
+ - spec/symbolmatrix/symbolmatrix_spec.rb
131
+ - spec/writer/symbolmatrix_spec.rb
132
+ has_rdoc:
@@ -1,35 +0,0 @@
1
- require "yaml"
2
-
3
- module YAML
4
- module SymbolMatrix
5
- # Calls #merge! using the parsed YAML data as argument
6
- def from_yaml yaml
7
- merge! YAML.load yaml
8
- end
9
-
10
- # Calls #merge! using the parsed YAML data from the file
11
- def from_file path
12
- merge! YAML.load_file path
13
- end
14
-
15
- # Can I override initialize and call super anyways??
16
- def initialize argument = nil
17
- end
18
- end
19
- end
20
-
21
- class SymbolMatrix
22
- include YAML::SymbolMatrix
23
-
24
- def initialize argument = nil
25
- if argument.is_a? String
26
- if File.exist? argument
27
- from_file argument
28
- else
29
- from_yaml argument
30
- end
31
- else
32
- merge! argument unless argument.nil?
33
- end
34
- end
35
- end
@@ -1,60 +0,0 @@
1
- require "symbolmatrix"
2
-
3
- require "fast" # For testing easyness
4
-
5
- describe YAML::SymbolMatrix do
6
- describe "#from_yaml" do
7
- it "should call #merge! on self using the parsed YAML data as argument" do
8
- sample_yaml = "a: { nested: { data: with, very: much }, content: to find }"
9
- the_stub = stub "a theoretical SymbolMatrix"
10
- the_stub.extend YAML::SymbolMatrix
11
- the_stub.should_receive(:merge!).with "a" => { "nested" => { "data" => "with", "very" => "much" }, "content" => "to find" }
12
- the_stub.from_yaml sample_yaml
13
- end
14
- end
15
-
16
- describe "#from_file" do
17
- context "there is a YAML file in the given path" do
18
- before do
19
- Fast.file.write "temp/data.yaml", "a: { nested: { data: with, very: much }, content: to find }"
20
- end
21
-
22
- it "should call #merge! on self using the parsed YAML data found in the file" do
23
- the_stub = stub "a theoretical SymbolMatrix"
24
- the_stub.extend YAML::SymbolMatrix
25
- the_stub.should_receive(:merge!).with "a" => { "nested" => { "data" => "with", "very" => "much" }, "content" => "to find" }
26
- the_stub.from_file "temp/data.yaml"
27
- end
28
-
29
- after do
30
- Fast.dir.remove! :temp
31
- end
32
- end
33
- end
34
- end
35
-
36
- describe SymbolMatrix do
37
- describe "#initialize" do # Soooooo meta... tell me its true!
38
- context "a valid path to a file is provided" do
39
- before do
40
- Fast.file.write "temp/data.yaml", "a: { nested: { data: with, very: much }, content: to find }"
41
- end
42
-
43
- it "should load the data into self" do
44
- f = SymbolMatrix.new "temp/data.yaml"
45
- f.a.nested.data.should == "with"
46
- end
47
-
48
- after do
49
- Fast.dir.remove! :temp
50
- end
51
- end
52
-
53
- context "a YAML string is provided" do
54
- it "should load the data into self" do
55
- e = SymbolMatrix.new "beta: { nano: { data: with, very: much }, content: to find }"
56
- e.beta.nano[:very].should == "much"
57
- end
58
- end
59
- end
60
- end