symbolmatrix 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - jruby-18mode
7
+ - jruby-19mode
8
+ - rbx-18mode
9
+ - rbx-19mode
10
+ - ree
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in symbolmatrix.gemspec
4
+ gemspec
5
+
6
+ # Travis CI me lo pide
7
+ group :test do
8
+ gem "rake"
9
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Fernando Via
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,111 @@
1
+ SymbolMatrix
2
+ ============
3
+
4
+ [![Build Status](https://secure.travis-ci.org/Fetcher/symbolmatrix.png)](http://travis-ci.org/Fetcher/symbolmatrix) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/Fetcher/symbolmatrix)
5
+
6
+ > Strongly inspired in [SymbolTable][symboltable] gem by [Michael Jackson][michael-jackson-home] (thanks a lot!)
7
+
8
+ **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
+
10
+ The showdown:
11
+
12
+ ```ruby
13
+ h = Hash.new
14
+ h[:a] = 1
15
+ h[:a] # => 1
16
+ h['a'] # => nil
17
+ h.a # => NoMethodError: undefined method `a' for {}:Hash
18
+
19
+ require 'symbolmatrix'
20
+
21
+ m = SymbolMatrix.new
22
+ m[:a] = 1
23
+ m[:a] # => 1
24
+ m['a'] # => 1
25
+ m.a # => 1
26
+ ```
27
+
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:
29
+
30
+ 1. **Recursive convertion to SymbolMatrix**
31
+
32
+ ```ruby
33
+ require "symbolmatrix"
34
+
35
+ m = SymbolMatrix.new :quantum => { :nano => "data" }
36
+
37
+ m.quatum.nano # => "data"
38
+ ```
39
+
40
+ 2. **YAML autoloading**
41
+
42
+ ```ruby
43
+ require "symbolmatrix"
44
+
45
+ m = SymbolMatrix.new "quantum: of solace"
46
+ m.quantum # => "of solace"
47
+
48
+ # Or alternatively
49
+ m.from_yaml "quantum: of solace"
50
+
51
+ # Provided a file exists "configuration.yaml" with "database_uri: mysql://root@localhost/database"
52
+ m.from_file "configuration.yaml"
53
+ m.database_uri # => "mysql://root@localhost/database"
54
+
55
+ # Or simply
56
+ m = SymbolMatrix.new "configuration.yaml"
57
+ ```
58
+
59
+ [symboltable]: https://github.com/mjijackson/symboltable
60
+ [michael-jackson-home]: http://mjijackson.com/
61
+
62
+ Further details
63
+ ---------------
64
+
65
+ ### Recursive `#to_hash` convertion
66
+
67
+ SymbolMatrix provides the `#to_hash` method that recursively transforms the matrix into a n-dimentional Hash.
68
+
69
+ ### Disabling the YAML discovery
70
+
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.
72
+
73
+ ### Exceptions
74
+
75
+ Whenever a key is not found in the SymbolMatrix, a custom `SymbolMatrix::KeyNotDefinedException` will be raised.
76
+ Similarly, if you attempt to use an inconvertible key (inconvertible to `Symbol`) a `SymbolMatrix::InvalidKeyException` will be raised.
77
+
78
+ Installation
79
+ ------------
80
+
81
+ gem install symbolmatrix
82
+
83
+ ### Or using Bundler
84
+ Add this line to your application's Gemfile:
85
+
86
+ gem 'symbolmatrix'
87
+
88
+ And then execute:
89
+
90
+ bundle install
91
+
92
+ ## Testing
93
+
94
+ RSpec specs are provided to check functionality.
95
+
96
+ ## License
97
+
98
+ Copyright (C) 2012 Fetcher
99
+
100
+ This program is free software: you can redistribute it and/or modify
101
+ it under the terms of the GNU General Public License as published by
102
+ the Free Software Foundation, either version 3 of the License, or
103
+ (at your option) any later version.
104
+
105
+ This program is distributed in the hope that it will be useful,
106
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
107
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
108
+ GNU General Public License for more details.
109
+
110
+ You should have received a copy of the GNU General Public License
111
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ desc "Run specs"
6
+ RSpec::Core::RakeTask.new(:spec) do |t|
7
+ t.pattern = "./spec/**/*_spec.rb"
8
+ end
9
+
10
+ task :default => :spec
@@ -0,0 +1,2 @@
1
+ require "symbolmatrix/symbolmatrix"
2
+ require "yaml/symbolmatrix"
@@ -0,0 +1,82 @@
1
+ require "symbolmatrix/version"
2
+
3
+ class SymbolMatrix < Hash
4
+
5
+ # Initializes the SymbolMatrix with the passed Hash if a hash is passed
6
+ def initialize hash = nil
7
+ super
8
+ merge! hash unless hash.nil?
9
+ end
10
+
11
+ # Validates whether the given key is usable in a SymbolMatrix
12
+ def validate_key key
13
+ unless key.respond_to? :to_sym
14
+ raise InvalidKeyException, "The key '#{key}' does not respond to #to_sym, so is not a valid key for SymbolMatrix"
15
+ end
16
+
17
+ return true
18
+ end
19
+
20
+ # Sets the value of the given +key+ to +val+ if the key is valid.
21
+ def store key, val
22
+ validate_key key
23
+ if val.instance_of? Hash
24
+ super(key.to_sym, SymbolMatrix.new(val))
25
+ else
26
+ super(key.to_sym, val)
27
+ end
28
+ end
29
+
30
+ # Retrieves the value of the given +key+.
31
+ def [] key
32
+ validate_key key
33
+ raise KeyNotDefinedException, "The key :#{key} is not defined" unless self.has_key? key.to_sym
34
+ super key.to_sym
35
+ end
36
+
37
+ alias []= store
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
51
+ end
52
+
53
+ # Merges the passed hash within self
54
+ def merge! hash
55
+ hash.each do |key, value|
56
+ store key, value
57
+ end
58
+ end
59
+
60
+ alias update merge!
61
+
62
+ # Checks the keys for compatibility with SymbolMatrix and calls the merge in Hash
63
+ def merge hash
64
+ # Before merging, let's check the keys
65
+ hash.each_key do |key|
66
+ validate_key key
67
+ end
68
+ super hash
69
+ end
70
+
71
+ # Allows values to be retrieved and set using Ruby's dot method syntax.
72
+ def method_missing sym, *args
73
+ if sym.to_s.index "="
74
+ store sym.to_s[0..-2].to_sym, args.shift
75
+ else
76
+ self[sym]
77
+ end
78
+ end
79
+
80
+ class KeyNotDefinedException < RuntimeError; end
81
+ class InvalidKeyException < RuntimeError; end
82
+ end
@@ -0,0 +1,3 @@
1
+ module Symbolmatrix
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,35 @@
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
@@ -0,0 +1,147 @@
1
+ require "symbolmatrix/symbolmatrix"
2
+
3
+ describe SymbolMatrix do
4
+
5
+ describe "#validate_key" do
6
+ context "an not convertible to Symbol key is passed" do
7
+ it "should raise a SymbolMatrix::InvalidKeyException" do
8
+ m = SymbolMatrix.new
9
+ o = Object.new
10
+ expect { m.validate_key o
11
+ }.to raise_error SymbolMatrix::InvalidKeyException, "The key '#{o}' does not respond to #to_sym, so is not a valid key for SymbolMatrix"
12
+ end
13
+ end
14
+ end
15
+
16
+ describe "#store" do
17
+ context "a key is stored using a symbol" do
18
+ it "should be foundable with #[<symbol]" do
19
+ a = SymbolMatrix.new
20
+ a.store :a, 2
21
+ a[:a].should == 2
22
+ end
23
+ end
24
+
25
+ context "the passed value is a Hash" do
26
+ it "should be converted into a SymbolTable" do
27
+ a = SymbolMatrix.new
28
+ a.store :b, { :c => 3 }
29
+ a[:b].should be_a SymbolMatrix
30
+ end
31
+ end
32
+ end
33
+
34
+ shared_examples_for "any merging operation" do
35
+ it "should call :store for every item in the passed Hash" do
36
+ m = SymbolMatrix.new
37
+ m.should_receive(:store).exactly(3).times
38
+ m.send @method, { :a => 1, :b => 3, :c => 4 }
39
+ end
40
+ end
41
+
42
+ describe "#merge!" do
43
+ before { @method = :merge! }
44
+ it_behaves_like "any merging operation"
45
+ end
46
+
47
+ describe "#update" do
48
+ before { @method = :update }
49
+ it_behaves_like "any merging operation"
50
+ end
51
+
52
+ describe "#merge" do
53
+ it "should call #validate_key for each passed item" do
54
+ m = SymbolMatrix.new
55
+ m.should_receive(:validate_key).exactly(3).times.and_return(true)
56
+ m.merge :a => 2, :b => 3, :c => 4
57
+ end
58
+ end
59
+
60
+ describe "#[]" do
61
+ context "the matrix is empty" do
62
+ it "should raise a SymbolMatrix::KeyNotDefinedException" do
63
+ m = SymbolMatrix.new
64
+ expect { m['t']
65
+ }.to raise_error SymbolMatrix::KeyNotDefinedException, "The key :t is not defined"
66
+ end
67
+ end
68
+
69
+ context "the matrix has a key defined using a symbol" do
70
+ it "should return the same value when called with a string" do
71
+ m = SymbolMatrix.new
72
+ m[:s] = 3
73
+ m["s"].should == 3
74
+ end
75
+ end
76
+ end
77
+
78
+ 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
107
+ end
108
+ end
109
+
110
+ describe ".new" do
111
+ context "a Hash is passed as argument" do
112
+ it "should accept it" do
113
+ m = SymbolMatrix.new :a => 1
114
+ m["a"].should == 1
115
+ m[:a].should == 1
116
+ end
117
+ end
118
+ end
119
+
120
+ describe "method_missing" do
121
+ it "should store in a key named after the method without the '=' sign" do
122
+ m = SymbolMatrix.new
123
+ m.a = 4
124
+ m[:a].should == 4
125
+ end
126
+
127
+ it "should return the same as the symbol representation of the method" do
128
+ m = SymbolMatrix.new
129
+ m.a = 3
130
+ m[:a].should == 3
131
+ m["a"].should == 3
132
+ m.a.should == 3
133
+ end
134
+
135
+ it "should preserve the class of the argument" do
136
+ class A < SymbolMatrix; end
137
+ class B < SymbolMatrix; end
138
+
139
+ a = A.new
140
+ b = B.new
141
+
142
+ a.a = b
143
+
144
+ a.a.should be_instance_of B
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,60 @@
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
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/symbolmatrix/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Xavier Via"]
6
+ gem.email = ["xavier.via.canel@gmail.com"]
7
+ gem.description = %q{Very useful for configuration files, SymbolMatrix is a hash-like multidimentional Symbol-only class with ability to discover and load YAML data}
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
+ gem.homepage = "http://github.com/fetcher/symbolmatrix"
10
+
11
+ gem.add_development_dependency "rspec"
12
+ gem.add_development_dependency "pry"
13
+ gem.add_development_dependency "fast"
14
+
15
+ gem.files = `git ls-files`.split($\)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.name = "symbolmatrix"
19
+ gem.require_paths = ["lib"]
20
+ gem.version = Symbolmatrix::VERSION
21
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: symbolmatrix
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Xavier Via
14
+ autorequire:
15
+ bindir: bin
16
+ 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
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ version_requirements: *id001
32
+ prerelease: false
33
+ name: rspec
34
+ - !ruby/object:Gem::Dependency
35
+ type: :development
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ 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
49
+ 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
+ prerelease: false
61
+ 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:
64
+ - xavier.via.canel@gmail.com
65
+ executables: []
66
+
67
+ extensions: []
68
+
69
+ extra_rdoc_files: []
70
+
71
+ files:
72
+ - .gitignore
73
+ - .travis.yml
74
+ - Gemfile
75
+ - LICENSE
76
+ - README.md
77
+ - Rakefile
78
+ - lib/symbolmatrix.rb
79
+ - lib/symbolmatrix/symbolmatrix.rb
80
+ - lib/symbolmatrix/version.rb
81
+ - lib/yaml/symbolmatrix.rb
82
+ - spec/symbolmatrix_spec.rb
83
+ - spec/yaml-symbolmatrix_spec.rb
84
+ - symbolmatrix.gemspec
85
+ homepage: http://github.com/fetcher/symbolmatrix
86
+ licenses: []
87
+
88
+ post_install_message:
89
+ rdoc_options: []
90
+
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ 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
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ hash: 3
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ requirements: []
112
+
113
+ rubyforge_project:
114
+ rubygems_version: 1.8.24
115
+ signing_key:
116
+ 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