symbolmatrix 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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