gamera-symbolmatrix 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.smas
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
+ yaml(File.read(path))
11
+ end
12
+
13
+ def yaml data
14
+ @source.merge! YAML.load(ERB.new(data).result)
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
@@ -0,0 +1,9 @@
1
+ require 'yaml'
2
+ require 'json'
3
+ require 'erb'
4
+ require 'discoverer'
5
+
6
+ require 'symbolmatrix/symbolmatrix'
7
+ require 'symbolmatrix/serialization'
8
+ require 'reader/symbolmatrix'
9
+ require 'writer/symbolmatrix'
@@ -0,0 +1,43 @@
1
+ class SymbolMatrix < Hash
2
+ class Serialization
3
+ def self.parse serialization
4
+ result = SymbolMatrix.new
5
+ return result if serialization.length == 0
6
+
7
+ if serialization.include? " "
8
+ serialization.split(" ").each do |command|
9
+ result = result.recursive_merge parse command
10
+ end
11
+ else
12
+ parts = serialization.split ":"
13
+ unless parts.first.include? "."
14
+ begin
15
+ parts[1] = Integer parts.last
16
+ rescue ArgumentError => e
17
+ end
18
+ result.merge! parts.first => parts.last
19
+ else
20
+ the_key = serialization[0..serialization.index(".") -1]
21
+ result[the_key] = parse serialization[serialization.index(".")+1..-1]
22
+ end
23
+ end
24
+ result
25
+ end
26
+ end
27
+
28
+ def initialize argument = nil
29
+ if argument.is_a? String
30
+ if File.exist? argument
31
+ from.file argument
32
+ else
33
+ begin
34
+ from.yaml argument
35
+ rescue NoMethodError => e
36
+ from.serialization argument
37
+ end
38
+ end
39
+ else
40
+ merge! argument unless argument.nil?
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,122 @@
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
+ # @deprecated Use #to.hash instead
40
+ def to_hash
41
+ Kernel.warn "[DEPRECATION]: #to_hash is deprecated, please use #to.hash instead"
42
+ end
43
+
44
+ # Merges the passed hash within self
45
+ def merge! hash
46
+ hash.each do |key, value|
47
+ store key, value
48
+ end
49
+ end
50
+
51
+ alias update merge!
52
+
53
+ # Checks the keys for compatibility with SymbolMatrix and calls the merge in Hash
54
+ def merge hash
55
+ # Before merging, let's check the keys
56
+ hash.each_key do |key|
57
+ validate_key key
58
+ end
59
+ super hash
60
+ end
61
+
62
+ # Allows values to be retrieved and set using Ruby's dot method syntax.
63
+ def method_missing sym, *args
64
+ if sym.to_s.index "="
65
+ store sym.to_s[0..-2].to_sym, args.shift
66
+ else
67
+ self[sym]
68
+ end
69
+ end
70
+
71
+ # Merges this SymbolMatrix with another SymbolMatrix recursively
72
+ def recursive_merge hash, override = false
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
+ if result[key].respond_to? :recursive_merge
81
+ result[key] = result[key].recursive_merge hash[key], override
82
+ else
83
+ if override
84
+ result[key] = hash[key]
85
+ else
86
+ raise MergeError, "The value of the :#{key} key is already defined. Run recursive merge with flag true if you want it to override"
87
+ end
88
+ end
89
+ else
90
+ result[key] = hash[key]
91
+ end
92
+ end
93
+ return result
94
+ end
95
+
96
+ # Merges recursively the passed SymbolMatrix into self
97
+ def recursive_merge! symbolmatrix, override = false
98
+ symbolmatrix.each do |key, value|
99
+ if self.has_key? key
100
+ if self[key].respond_to? :recursive_merge!
101
+ self[key].recursive_merge! value, override
102
+ else
103
+ if override
104
+ self[key] = value
105
+ else
106
+ raise MergeError, "The value of the :#{key} key is already defined. Run recursive merge with flag true if you want it to override"
107
+ end
108
+ end
109
+ else
110
+ self[key] = value
111
+ end
112
+ end
113
+ end
114
+
115
+ class KeyNotDefinedException < NoMethodError; end
116
+ class InvalidKeyException < RuntimeError; end
117
+ class MergeError < RuntimeError; end
118
+ end
119
+
120
+ def SymbolMatrix *args
121
+ SymbolMatrix.new *args
122
+ end
@@ -0,0 +1,3 @@
1
+ module Symbolmatrix
2
+ VERSION = "1.2.1"
3
+ end
@@ -0,0 +1,59 @@
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
+
35
+ def json
36
+ @source.to_json
37
+ end
38
+
39
+ def yaml
40
+ string_key_hash.to_yaml
41
+ end
42
+
43
+ def string_key_hash
44
+ the_hash = {}
45
+ @source.each do |key, value|
46
+ if value.respond_to? :to
47
+ the_hash[key.to_s] = value.to.string_key_hash
48
+ else
49
+ the_hash[key.to_s] = value
50
+ end
51
+ end
52
+ the_hash
53
+ end
54
+ end
55
+ end
56
+
57
+ class SymbolMatrix < Hash
58
+ include Discoverer::Writer
59
+ 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,149 @@
1
+ require 'complete_features_helper'
2
+
3
+ describe Reader::SymbolMatrix do
4
+ describe '#initialize' do
5
+ it 'receives a source and add it as source' do
6
+ source = double 'source'
7
+ reader = Reader::SymbolMatrix.new source
8
+ expect(reader.source).to eq source
9
+ end
10
+ end
11
+
12
+ describe "#yaml" do
13
+ shared_examples_for "parsed YAML" do
14
+ it "calls #merge! the source using the parsed YAML data as argument" do
15
+ the_stub = double "a theoretical SymbolMatrix"
16
+ reader = Reader::SymbolMatrix.new the_stub
17
+ expect(the_stub).to receive(:merge!).with parsed_hash
18
+ reader.yaml sample_yaml
19
+ end
20
+ end
21
+
22
+ context "with YAML" do
23
+ let(:sample_yaml) { "a: { nested: { data: with, very: much }, content: to find }" }
24
+ let(:parsed_hash) {
25
+ {
26
+ "a" => {
27
+ "nested" => {
28
+ "data" => "with",
29
+ "very" => "much"
30
+ },
31
+ "content" => "to find"
32
+ }
33
+ }
34
+ }
35
+
36
+ it_behaves_like "parsed YAML"
37
+ end
38
+
39
+ context "with YAML containing ERB" do
40
+ let(:sample_yaml) { "a: { nested: { data: with, very: much }, content: <%= 'to find' %> }" }
41
+ let(:parsed_hash) {
42
+ {
43
+ "a" => {
44
+ "nested" => {
45
+ "data" => "with",
46
+ "very" => "much"
47
+ },
48
+ "content" => "to find"
49
+ }
50
+ }
51
+ }
52
+
53
+ it_behaves_like "parsed YAML"
54
+ end
55
+ end
56
+
57
+ describe "#file" do
58
+ shared_examples_for "parsed file" do
59
+ let(:path) { File.join('temp', file) }
60
+
61
+ around do |example|
62
+ Fast.file.write path, yaml
63
+ example.run
64
+ Fast.dir.remove! :temp
65
+ end
66
+
67
+ it "calls #merge! on the source using the parsed YAML data found in the file" do
68
+ the_stub = double "a theoretical SymbolMatrix"
69
+ reader = Reader::SymbolMatrix.new the_stub
70
+ expect(the_stub).to receive(:merge!).with parsed_hash
71
+ reader.file path
72
+ end
73
+ end
74
+
75
+ context "there is a YAML file in the given path" do
76
+ let(:file) { 'data.yaml' }
77
+ let(:yaml) { "a: { nested: { data: with, very: much }, content: to find }" }
78
+ let(:parsed_hash) {
79
+ {
80
+ "a" => {
81
+ "nested" => {
82
+ "data" => "with",
83
+ "very" => "much"
84
+ },
85
+ "content" => "to find"
86
+ }
87
+ }
88
+ }
89
+
90
+ it_behaves_like "parsed file"
91
+ end
92
+
93
+ context "there is a YAML file with ERB in the given path" do
94
+ let(:file) { 'data.yaml' }
95
+ let(:yaml) { "a: { nested: { data: with, very: much }, content: <%= 'to find' %> }" }
96
+ let(:parsed_hash) {
97
+ {
98
+ "a" => {
99
+ "nested" => {
100
+ "data" => "with",
101
+ "very" => "much"
102
+ },
103
+ "content" => "to find"
104
+ }
105
+ }
106
+ }
107
+
108
+ it_behaves_like "parsed file"
109
+ end
110
+ end
111
+
112
+ shared_examples_for "any reader serialization" do
113
+ it 'calls merge! to source with the parsed data' do
114
+ the_sm = double 'sm'
115
+ data_stub = double 'data'
116
+ ready_to_merge = double 'ready to merge'
117
+ reader = Reader::SymbolMatrix.new the_sm
118
+ expect(SymbolMatrix::Serialization).to receive(:parse).with(data_stub).and_return ready_to_merge
119
+ expect(the_sm).to receive(:merge!).with ready_to_merge
120
+ reader.send @method, data_stub
121
+ end
122
+ end
123
+
124
+ describe "#serialization" do
125
+ before { @method = :serialization }
126
+ it_behaves_like 'any reader serialization'
127
+ end
128
+
129
+ describe '#smas' do
130
+ before { @method = :smas }
131
+ it_behaves_like 'any reader serialization'
132
+ end
133
+ end
134
+
135
+ describe SymbolMatrix do
136
+ it 'includes the Discoverer for Reader' do
137
+ expect(SymbolMatrix.ancestors).to include Discoverer::Reader
138
+ end
139
+
140
+ it 'features a deprecation notice in #from_yaml' do
141
+ expect(Kernel).to receive(:warn).with "[DEPRECATION]: #from_yaml is deprecated, please use #from.yaml instead"
142
+ SymbolMatrix.new.from_yaml double 'argument'
143
+ end
144
+
145
+ it 'features a deprecation notice in #from_file' do
146
+ expect(Kernel).to receive(:warn).with "[DEPRECATION]: #from_file is deprecated, please use #from.file instead"
147
+ SymbolMatrix.new.from_file double 'argument'
148
+ end
149
+ end