yaml_pack 0.0.1.alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.md +1 -0
- data/Rakefile +5 -0
- data/lib/core_ext/hash.rb +17 -0
- data/lib/yaml_pack.rb +85 -0
- data/spec/.DS_Store +0 -0
- data/spec/fixtures/.DS_Store +0 -0
- data/spec/fixtures/yaml_pack/countries/sweden.yml +3 -0
- data/spec/fixtures/yaml_pack/empty.yml +0 -0
- data/spec/fixtures/yaml_pack/names.yml +9 -0
- data/spec/fixtures/yaml_pack/names_german.yml +3 -0
- data/spec/fixtures/yaml_pack/population.yml +9 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/yaml_pack/yaml_pack_spec.rb +82 -0
- data/yaml_pack.gemspec +25 -0
- metadata +83 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# YamlPack
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Extend Hash with recursive merging abilities
|
2
|
+
class Hash
|
3
|
+
# Deep merge method. Silly name prevents overwriting other implementations.
|
4
|
+
#
|
5
|
+
# Inspired from:
|
6
|
+
# http://www.gemtacular.com/gemdocs/cerberus-0.2.2/doc/classes/Hash.html
|
7
|
+
# File lib/cerberus/utils.rb, line 42
|
8
|
+
def yaml_pack_deep_merge!(second)
|
9
|
+
second.each_pair do |k,v|
|
10
|
+
if self[k].is_a?(Hash) and second[k].is_a?(Hash)
|
11
|
+
self[k].yaml_pack_deep_merge!(second[k])
|
12
|
+
else
|
13
|
+
self[k] = second[k]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/yaml_pack.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'core_ext/hash'
|
2
|
+
|
3
|
+
class YamlPack
|
4
|
+
VERSION = "0.0.1.alpha"
|
5
|
+
|
6
|
+
KEY_CONVERTERS = {
|
7
|
+
:symbolize => Proc.new{|key, previous_keys| key.respond_to?(:to_sym) ? key.to_sym : key }
|
8
|
+
}.freeze
|
9
|
+
|
10
|
+
attr_reader :files, :base_dir
|
11
|
+
|
12
|
+
def self.load_deep_merged(files, opts = {})
|
13
|
+
new(files, opts).load_deep_merged
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(files, opts = {})
|
17
|
+
@files = [files].flatten
|
18
|
+
|
19
|
+
@base_dir = opts.fetch(:base_dir, nil)
|
20
|
+
@with_erb = opts.fetch(:erb, true)
|
21
|
+
@key_converter = opts.fetch(:key_converter, nil)
|
22
|
+
@header_file = opts.fetch(:header_file, nil)
|
23
|
+
|
24
|
+
if KEY_CONVERTERS.has_key?(@key_converter)
|
25
|
+
@key_converter = KEY_CONVERTERS[@key_converter]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def load_deep_merged
|
30
|
+
hsh = {}
|
31
|
+
|
32
|
+
files.select{|f| File.exists?(f) }.each do |f|
|
33
|
+
content = self.content(f)
|
34
|
+
content = ERB.new(content).result(binding) if @with_erb
|
35
|
+
|
36
|
+
result = YAML::load(content) || {}
|
37
|
+
result = prepend_subfolders(f, result) if @base_dir
|
38
|
+
result = convert_keys_recursive(result) if @key_converter
|
39
|
+
|
40
|
+
hsh.yaml_pack_deep_merge!(result)
|
41
|
+
end
|
42
|
+
|
43
|
+
hsh
|
44
|
+
end
|
45
|
+
|
46
|
+
def content(file_path)
|
47
|
+
body = File.read(file_path) || ""
|
48
|
+
header + body
|
49
|
+
end
|
50
|
+
|
51
|
+
def header
|
52
|
+
(@header_file && File.exists?(@header_file)) ? File.read(@header_file) : ""
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.subfolders(base_dir, file_path)
|
56
|
+
base_dir = "#{base_dir}/".gsub("//", '/') # hack to always have a trailing /
|
57
|
+
file_path.gsub(/^#{base_dir}/, '').split('/')[0...-1]
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
|
62
|
+
|
63
|
+
def convert_keys_recursive(result, previous_keys = [])
|
64
|
+
if result.is_a?(Hash)
|
65
|
+
hsh = {}
|
66
|
+
result.each do |key, value|
|
67
|
+
converted_key = @key_converter.call(key, previous_keys)
|
68
|
+
hsh[converted_key] = convert_keys_recursive(value, [*previous_keys, key])
|
69
|
+
end
|
70
|
+
hsh
|
71
|
+
else # If it's not a hash, return the object itself (end of recursion)
|
72
|
+
result
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def prepend_subfolders(file_path, object)
|
77
|
+
subfolders(file_path).inject(object) do |object, subfolder|
|
78
|
+
{subfolder => object}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def subfolders(file_path)
|
83
|
+
self.class.subfolders(base_dir, file_path)
|
84
|
+
end
|
85
|
+
end
|
data/spec/.DS_Store
ADDED
Binary file
|
Binary file
|
File without changes
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'yaml_pack'
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe YamlPack do
|
5
|
+
it "should load empty file and return empty hash" do
|
6
|
+
result = YamlPack.new('spec/fixtures/yaml_pack/empty.yml').load_deep_merged
|
7
|
+
|
8
|
+
result.should == {}
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should load one yaml file" do
|
12
|
+
result = YamlPack.new('spec/fixtures/yaml_pack/names.yml').load_deep_merged
|
13
|
+
|
14
|
+
result['countries']['ch']['name'].should == 'Switzerland'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should convert keys" do
|
18
|
+
f = 'spec/fixtures/yaml_pack/names.yml'
|
19
|
+
toolbox = YamlPack.new(f, :key_converter => Proc.new{|k| k.to_sym})
|
20
|
+
result = toolbox.load_deep_merged
|
21
|
+
result[:countries][:ch][:name].should == 'Switzerland'
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
it "should allow for key_converters with previous keys" do
|
26
|
+
f = 'spec/fixtures/yaml_pack/names.yml'
|
27
|
+
toolbox = YamlPack.new(f, :key_converter => Proc.new{|key, previous_keys| [previous_keys, key].flatten.join("_")})
|
28
|
+
result = toolbox.load_deep_merged
|
29
|
+
result['countries']['countries_ch']['countries_ch_name'].should == 'Switzerland'
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
it "should merge two yaml files" do
|
34
|
+
files = [
|
35
|
+
'spec/fixtures/yaml_pack/names.yml',
|
36
|
+
'spec/fixtures/yaml_pack/population.yml'
|
37
|
+
]
|
38
|
+
|
39
|
+
result = YamlPack.new(files).load_deep_merged
|
40
|
+
|
41
|
+
# deep merge ch
|
42
|
+
result['countries']['ch']['name'].should == 'Switzerland'
|
43
|
+
result['countries']['ch']['population'].should == 8
|
44
|
+
# items specific to population.yml
|
45
|
+
result['countries']['it']['population'].should == 56
|
46
|
+
# items specific to names.yml
|
47
|
+
result['countries']['pl']['name'].should == 'Poland'
|
48
|
+
end
|
49
|
+
|
50
|
+
it "files should overwrite previous files" do
|
51
|
+
files = [
|
52
|
+
'spec/fixtures/yaml_pack/names.yml',
|
53
|
+
'spec/fixtures/yaml_pack/names_german.yml'
|
54
|
+
]
|
55
|
+
|
56
|
+
result = YamlPack.new(files).load_deep_merged
|
57
|
+
result['countries']['ch']['name'].should == 'Schweiz'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "replicate nesting of subfolders into resulting hash" do
|
61
|
+
files = [
|
62
|
+
'spec/fixtures/yaml_pack/names.yml',
|
63
|
+
'spec/fixtures/yaml_pack/countries/sweden.yml'
|
64
|
+
]
|
65
|
+
|
66
|
+
result = YamlPack.new(files, :base_dir => 'spec/fixtures/yaml_pack').load_deep_merged
|
67
|
+
result['countries']['ch']['name'].should == 'Switzerland'
|
68
|
+
result['countries']['se']['name'].should == 'Sweden'
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
it "#subfolders" do
|
73
|
+
YamlPack.subfolders("/foo/", "/foo/baz.yml").should == []
|
74
|
+
YamlPack.subfolders("/foo/", "/foo/bar/baz.yml").should == ['bar']
|
75
|
+
YamlPack.subfolders("/foo/", "/foo/bar/baz/lorem.yml").should == ['bar', 'baz']
|
76
|
+
|
77
|
+
YamlPack.subfolders("foo/", "foo/bar/baz.yml").should == ['bar']
|
78
|
+
YamlPack.subfolders("/foo", "/foo/baz.yml").should == []
|
79
|
+
YamlPack.subfolders("", "/foo/baz.yml").should == ['foo']
|
80
|
+
YamlPack.subfolders(nil, "/foo/baz.yml").should == ['foo']
|
81
|
+
end
|
82
|
+
end
|
data/yaml_pack.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "yaml_pack"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "yaml_pack"
|
7
|
+
s.version = YamlPack::VERSION
|
8
|
+
s.authors = ["sebastian"]
|
9
|
+
s.email = ["sebastian.burkhard@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Framework for complex yaml configuration file structures.}
|
12
|
+
s.description = %q{
|
13
|
+
YamlPack is a small framework for writing large and complex configuration files in yml.
|
14
|
+
It supports nesting and merging merging yaml files.
|
15
|
+
}
|
16
|
+
|
17
|
+
s.rubyforge_project = "yaml_pack"
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
s.add_development_dependency "rspec"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: yaml_pack
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.alpha
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- sebastian
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70121952134780 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70121952134780
|
25
|
+
description: ! "\n YamlPack is a small framework for writing large and complex
|
26
|
+
configuration files in yml.\n It supports nesting and merging merging yaml files.\n
|
27
|
+
\ "
|
28
|
+
email:
|
29
|
+
- sebastian.burkhard@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- Gemfile
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- lib/core_ext/hash.rb
|
39
|
+
- lib/yaml_pack.rb
|
40
|
+
- spec/.DS_Store
|
41
|
+
- spec/fixtures/.DS_Store
|
42
|
+
- spec/fixtures/yaml_pack/countries/sweden.yml
|
43
|
+
- spec/fixtures/yaml_pack/empty.yml
|
44
|
+
- spec/fixtures/yaml_pack/names.yml
|
45
|
+
- spec/fixtures/yaml_pack/names_german.yml
|
46
|
+
- spec/fixtures/yaml_pack/population.yml
|
47
|
+
- spec/spec_helper.rb
|
48
|
+
- spec/yaml_pack/yaml_pack_spec.rb
|
49
|
+
- yaml_pack.gemspec
|
50
|
+
homepage: ''
|
51
|
+
licenses: []
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>'
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 1.3.1
|
68
|
+
requirements: []
|
69
|
+
rubyforge_project: yaml_pack
|
70
|
+
rubygems_version: 1.8.11
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: Framework for complex yaml configuration file structures.
|
74
|
+
test_files:
|
75
|
+
- spec/fixtures/.DS_Store
|
76
|
+
- spec/fixtures/yaml_pack/countries/sweden.yml
|
77
|
+
- spec/fixtures/yaml_pack/empty.yml
|
78
|
+
- spec/fixtures/yaml_pack/names.yml
|
79
|
+
- spec/fixtures/yaml_pack/names_german.yml
|
80
|
+
- spec/fixtures/yaml_pack/population.yml
|
81
|
+
- spec/spec_helper.rb
|
82
|
+
- spec/yaml_pack/yaml_pack_spec.rb
|
83
|
+
has_rdoc:
|