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 ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ bin/*
3
+ .rspec
4
+ .bundle
5
+ Gemfile.lock
6
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in yaml_pack.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # YamlPack
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task default: :spec
@@ -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
@@ -0,0 +1,3 @@
1
+ se:
2
+ name: Sweden
3
+ population: 11
File without changes
@@ -0,0 +1,9 @@
1
+ countries:
2
+ ch:
3
+ name: Switzerland
4
+ de:
5
+ name: Germany
6
+ fr:
7
+ name: France
8
+ pl:
9
+ name: Poland
@@ -0,0 +1,3 @@
1
+ countries:
2
+ ch:
3
+ name: Schweiz
@@ -0,0 +1,9 @@
1
+ countries:
2
+ ch:
3
+ population: 8
4
+ de:
5
+ population: 80
6
+ fr:
7
+ population: 55
8
+ it:
9
+ population: 56
@@ -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: