gamera-symbolmatrix 1.2.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.
@@ -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