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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +10 -0
- data/Gemfile +18 -0
- data/Guardfile +39 -0
- data/LICENSE +22 -0
- data/README.md +201 -0
- data/Rakefile +10 -0
- data/features/parse_serialization.feature +26 -0
- data/features/print_to_yaml.feature +20 -0
- data/features/serialize.feature +43 -0
- data/features/stepdefs/parse_serialization.rb +11 -0
- data/features/stepdefs/print_to_yaml.rb +7 -0
- data/features/stepdefs/serialize.rb +11 -0
- data/features/support/env.rb +3 -0
- data/lib/reader/symbolmatrix.rb +37 -0
- data/lib/symbolmatrix.rb +9 -0
- data/lib/symbolmatrix/serialization.rb +43 -0
- data/lib/symbolmatrix/symbolmatrix.rb +122 -0
- data/lib/symbolmatrix/version.rb +3 -0
- data/lib/writer/symbolmatrix.rb +59 -0
- data/spec/complete_features_helper.rb +3 -0
- data/spec/plain_symbolmatrix_helper.rb +1 -0
- data/spec/reader/symbolmatrix_spec.rb +149 -0
- data/spec/symbolmatrix/serialization_spec.rb +133 -0
- data/spec/symbolmatrix/symbolmatrix_spec.rb +275 -0
- data/spec/writer/symbolmatrix_spec.rb +204 -0
- data/symbolmatrix.gemspec +22 -0
- metadata +133 -0
@@ -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,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
|
data/lib/symbolmatrix.rb
ADDED
@@ -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,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 @@
|
|
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
|