app-configs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 44bd83dad8cb131fa7e09b15221e6e350d3d8ade763687869598c12e41c02217
4
+ data.tar.gz: 880fc5ec782b3de5bb62263955a9576065253d2e8c95f1b37f674cfea088f3e0
5
+ SHA512:
6
+ metadata.gz: 7fc746a8a7303a999f99f972024b3f4633de850e5d07357a492c60c39afa3980e6f259c443f885bea69fc13eeb5ad11b2c54d19effd89d499e5cf419acc129a7
7
+ data.tar.gz: 42dc9f7c3eae289fa80f08e1e8d0cba0981579f4e74a99d5d1ee3166a65de2d4175a1ca3c3f3d64753f6e4e25991bc582b2a18e81c3efe2e6b420a556a1ac90a
@@ -0,0 +1,23 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ /vendor/
16
+ *.pid
17
+ *.log
18
+ *.log.*
19
+ /var/
20
+ /log/
21
+ *.swp
22
+ /.rspec_status
23
+
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.7.1
6
+ before_install: gem install bundler -v 2.1.4
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in application-config.gemspec
4
+ gemspec
5
+
@@ -0,0 +1,153 @@
1
+ = App::Config
2
+
3
+ Yet another library for load/save configuration files.
4
+
5
+ == Features
6
+
7
+ * Read the configuration files (default, startup, modified) in order and apply by overwriting.
8
+ * The modified configuration can be saved as a file in a given directory.
9
+ * File type Supports Ruby scripts, YAML and JSON.
10
+
11
+ == Installation
12
+
13
+ Add this line to your app's Gemfile:
14
+
15
+ [source,ruby]
16
+ ----
17
+ gem 'app-configs'
18
+ ----
19
+
20
+ And then execute:
21
+
22
+ $ bundle install
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install app-configs
27
+ or
28
+ $ gem install -l app-configs-x.x.x.gem
29
+
30
+ == Usage
31
+
32
+ === Example 1
33
+
34
+ [source,ruby]
35
+ ----
36
+ require "app-config"
37
+
38
+ # initial load. default search paths: "./config/defaults:./config:./var"
39
+ config = App::Config.new
40
+
41
+ puts config["test"]["lastdate"]
42
+
43
+ # update content.
44
+ config["test"]["lastdate"] = Time.now.to_s
45
+ pp config["test"]
46
+
47
+ # save section changes. (default: "./var")
48
+ config.save("test")
49
+ pp config["test"]
50
+
51
+ # load section.
52
+ config.load("test")
53
+ pp config["test"]
54
+
55
+ # remove modification and load original section
56
+ config.reset("test")
57
+ pp config["test"]
58
+
59
+ # reload all section.
60
+ config.reload
61
+ pp config
62
+ ----
63
+
64
+ == Reference
65
+
66
+ === Create a new App::Config::* with conditions.
67
+
68
+ [source,ruby]
69
+ ----
70
+ App::Config.new( type = nil, root: nil, path: nil )
71
+ App::Config::RUBY.new( root: nil, path: nil )
72
+ App::Config::YAML.new( root: nil, path: nil )
73
+ App::Config::JSON.new( root: nil, path: nil )
74
+ ----
75
+
76
+ * Result:
77
+ ** App::Config::{RUBY,YAML,JSON} object.
78
+
79
+ * Parameter:
80
+ ** type: Configulation file type. RUBY, YAML, or JSON. (default: YAML)
81
+ ** root: App root directory. (default: ".")
82
+ ** path: The directories for search and load file(s). (default: "$ROOT/config/defaults/:$ROOT/config:$ROOT/var")
83
+
84
+ === Reload all section(s).
85
+
86
+ [source,ruby]
87
+ ----
88
+ App::Config::RUBY#reload( root: nil, path: nil )
89
+ App::Config::YAML#reload( root: nil, path: nil )
90
+ App::Config::JSON#reload( root: nil, path: nil )
91
+ ----
92
+
93
+ * Result:
94
+ ** nil.
95
+
96
+ * Parameter:
97
+ ** root: App root directory. (default: ".")
98
+ ** path: The directories for search and load file(s). (default: "$ROOT/config/defaults/:$ROOT/config:$ROOT/var")
99
+
100
+ === Load the section.
101
+
102
+ [source,ruby]
103
+ ----
104
+ App::Config::RUBY#load( section )
105
+ App::Config::YAML#load( section )
106
+ App::Config::JSON#load( section )
107
+ ----
108
+
109
+ * Result:
110
+ ** nil.
111
+
112
+ * Parameter:
113
+ ** section: Section name for load.
114
+
115
+ === Save section changes. (default: "./var")
116
+
117
+ [source,ruby]
118
+ ----
119
+ App::Config::RUBY#save( section )
120
+ App::Config::YAML#save( section )
121
+ App::Config::JSON#save( section )
122
+ ----
123
+
124
+ * Result:
125
+ ** nil.
126
+
127
+ * Parameter:
128
+ ** section: Section name for save.
129
+
130
+ === Remove modification and load original section
131
+
132
+ [source,ruby]
133
+ ----
134
+ App::Config::RUBY#reset( section )
135
+ App::Config::YAML#reset( section )
136
+ App::Config::JSON#reset( section )
137
+ ----
138
+
139
+ * Result:
140
+ ** nil.
141
+
142
+ * Parameter:
143
+ ** section: Section name for reset.
144
+
145
+ == Contributing
146
+
147
+ Bug reports and pull requests are welcome on GitHub at https://github.com/arimay/app-configs.
148
+
149
+ == License
150
+
151
+ The gem is available as open source under the terms of the http://opensource.org/licenses/MIT[MIT License].
152
+
153
+ Copyright (c) ARIMA Yasuhiro <arima.yasuhiro@gmail.com>
@@ -0,0 +1,153 @@
1
+ = App::Config
2
+
3
+ またもや構成ファイル読み込み/書き出しライブラリ.
4
+
5
+ == 特徴
6
+
7
+ * 構成ファイル(デフォルト、スタートアップ、更新分)を順番に読み取り、上書きして適用する.
8
+ * 変更した構成は、所定のディレクトリにファイルとして保存することができる.
9
+ * ファイルタイプ Rubyスクリプト、YAML、JSON をサポートする.
10
+
11
+ == 導入
12
+
13
+ アプリの Gemfile にこの行を追加
14
+
15
+ [source,ruby]
16
+ ----
17
+ gem 'app-configs'
18
+ ----
19
+
20
+ それから実行
21
+
22
+ $ bundle install
23
+
24
+ または次のように手動で導入
25
+
26
+ $ gem install app-configs
27
+ or
28
+ $ gem install -l app-configs-x.x.x.gem
29
+
30
+ == 使い方
31
+
32
+ === Example 1
33
+
34
+ [source,ruby]
35
+ ----
36
+ require "app-config"
37
+
38
+ # 初期読み込み. 初期探索パス: "./config/defaults:./config:./var"
39
+ config = App::Config.new
40
+
41
+ puts config["test"]["lastdate"]
42
+
43
+ # 内容を更新する
44
+ config["test"]["lastdate"] = Time.now.to_s
45
+ pp config["test"]
46
+
47
+ # セクションの変更を保存する (default: "./var")
48
+ config.save("test")
49
+ pp config["test"]
50
+
51
+ # セクションを読み込む
52
+ config.load("test")
53
+ pp config["test"]
54
+
55
+ # セクションの変更を削除して元内容を読み込む
56
+ config.reset("test")
57
+ pp config["test"]
58
+
59
+ # 全セクションを読み込む
60
+ config.reload
61
+ pp config
62
+ ----
63
+
64
+ == リファレンス
65
+
66
+ === 条件を指定して、新たな App::Config::* を作成する.
67
+
68
+ [source,ruby]
69
+ ----
70
+ App::Config.new( type = nil, root: nil, path: nil )
71
+ App::Config::RUBY.new( root: nil, path: nil )
72
+ App::Config::YAML.new( root: nil, path: nil )
73
+ App::Config::JSON.new( root: nil, path: nil )
74
+ ----
75
+
76
+ * Result:
77
+ ** App::Config::{RUBY,YAML,JSON} オブジェクト.
78
+
79
+ * Parameter:
80
+ ** type: 構成ファイルタイプ. RUBY, YAML, または JSON. (default: YAML)
81
+ ** root: アプリの基準ディレクトリ. (default: ".")
82
+ ** path: 探索と読み込み対象のディレクトリ. (default: "$ROOT/config/defaults/:$ROOT/config:$ROOT/var")
83
+
84
+ === Reload all section(s).
85
+
86
+ [source,ruby]
87
+ ----
88
+ App::Config::RUBY#reload( root: nil, path: nil )
89
+ App::Config::YAML#reload( root: nil, path: nil )
90
+ App::Config::JSON#reload( root: nil, path: nil )
91
+ ----
92
+
93
+ * Result:
94
+ ** nil.
95
+
96
+ * Parameter:
97
+ ** root: アプリの基準ディレクトリ. (default: ".")
98
+ ** path: 探索と読み込み対象のディレクトリ. (default: "$ROOT/config/defaults/:$ROOT/config:$ROOT/var")
99
+
100
+ === セクションを読み込む
101
+
102
+ [source,ruby]
103
+ ----
104
+ App::Config::RUBY#load( section )
105
+ App::Config::YAML#load( section )
106
+ App::Config::JSON#load( section )
107
+ ----
108
+
109
+ * Result:
110
+ ** nil.
111
+
112
+ * Parameter:
113
+ ** section: 読み込み対象のセクション.
114
+
115
+ === セクションを書き出す
116
+
117
+ [source,ruby]
118
+ ----
119
+ App::Config::RUBY#save( section )
120
+ App::Config::YAML#save( section )
121
+ App::Config::JSON#save( section )
122
+ ----
123
+
124
+ * Result:
125
+ ** nil.
126
+
127
+ * Parameter:
128
+ ** section: 書き込み対象のセクション.
129
+
130
+ === セクションを初期化
131
+
132
+ [source,ruby]
133
+ ----
134
+ App::Config::RUBY#reset( section )
135
+ App::Config::YAML#reset( section )
136
+ App::Config::JSON#reset( section )
137
+ ----
138
+
139
+ * Result:
140
+ ** nil.
141
+
142
+ * Parameter:
143
+ ** section: 初期化対象のセクション.
144
+
145
+ == 貢献
146
+
147
+ 不具合報告とプルリクエストは GitHub https://github.com/arimay/app-configs まで.
148
+
149
+ == ライセンス
150
+
151
+ この Gem は、 http://opensource.org/licenses/MIT[MITライセンス] の条件に基づいてオープンソースとして入手できる.
152
+
153
+ Copyright (c) ARIMA Yasuhiro <arima.yasuhiro@gmail.com>
@@ -0,0 +1,96 @@
1
+ require "bundler/gem_helper"
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ class Bundler::GemHelper
10
+
11
+ def git_archive( dir = "../zip" )
12
+ FileUtils.mkdir_p dir
13
+ dest_path = File.join(dir, "#{name}-#{version}.zip")
14
+ cmnd = "git archive --format zip --prefix=#{name}/ HEAD > #{dest_path}"
15
+
16
+ out, code = sh_with_status( cmnd )
17
+ raise "Couldn't archive gem," unless code == 0
18
+
19
+ Bundler.ui.confirm "#{name} #{version} archived to #{dest_path}."
20
+ end
21
+
22
+ def git_push
23
+ ver = version.to_s
24
+
25
+ cmnd = "git push origin #{ver} "
26
+ out, code = sh_with_status( cmnd )
27
+ raise "Couldn't git push origin." unless code == 0
28
+
29
+ cmnd = "git push "
30
+ out, code = sh_with_status( cmnd )
31
+ raise "Couldn't git push." unless code == 0
32
+
33
+ Bundler.ui.confirm "Git Push #{ver}."
34
+ end
35
+
36
+ def update_version( new_version )
37
+ version_filename = %x[ find . -type f -name "version.rb" | grep -v vendor | head -1 ].chomp
38
+ version_pathname = File.expand_path( version_filename )
39
+ lines = File.open( version_pathname ).read
40
+ lines = lines.gsub( /VERSION\s*=\s*\"\d+\.\d+\.\d+\"/, "VERSION = \"#{new_version}\"" )
41
+ File.open( version_pathname, "w" ) do |file|
42
+ file.write( lines )
43
+ end
44
+
45
+ cmnd = "git add #{version_pathname} "
46
+ out, code = sh_with_status( cmnd )
47
+ raise "Couldn't git add," unless code == 0
48
+
49
+ cmnd = "git commit -m '#{new_version}' "
50
+ out, code = sh_with_status( cmnd )
51
+ raise "Couldn't git commit." unless code == 0
52
+
53
+ cmnd = "git tag #{new_version} "
54
+ out, code = sh_with_status( cmnd )
55
+ raise "Couldn't git tag." unless code == 0
56
+
57
+ Bundler.ui.confirm "Update Tags to #{new_version}."
58
+ end
59
+
60
+ end
61
+
62
+ Bundler::GemHelper.new(Dir.pwd).instance_eval do
63
+
64
+ desc "Archive #{name}-#{version}.zip from repository"
65
+ task 'zip' do
66
+ git_archive
67
+ end
68
+
69
+ desc "Git Push"
70
+ task 'push' do
71
+ git_push
72
+ end
73
+
74
+ desc "Update Version Tiny"
75
+ task 'tiny' do
76
+ major, minor, tiny = version.to_s.split('.')
77
+ new_version = [major, minor, tiny.to_i + 1].join('.')
78
+ update_version( new_version )
79
+ end
80
+
81
+ desc "Update Version Minor"
82
+ task 'minor' do
83
+ major, minor, tiny = version.to_s.split('.')
84
+ new_version = [major, minor.to_i + 1, 0].join('.')
85
+ update_version( new_version )
86
+ end
87
+
88
+ desc "Update Version Major"
89
+ task 'major' do
90
+ major, minor, tiny = version.to_s.split('.')
91
+ new_version = [major.to_i + 1, 0, 0].join('.')
92
+ update_version( new_version )
93
+ end
94
+
95
+ end
96
+
@@ -0,0 +1,23 @@
1
+ require_relative 'lib/app/config/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "app-configs"
5
+ spec.version = App::Config::VERSION
6
+ spec.authors = ["arimay"]
7
+ spec.email = ["arima.yasuhiro@gmail.com"]
8
+
9
+ spec.summary = %q{ Application config loader/saver. }
10
+ spec.description = %q{ Yet another library for load/save app config files. }
11
+ spec.homepage = "https://github.com/arimay/app-configs"
12
+ spec.license = "MIT"
13
+
14
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
15
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ end
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "rake", "~> 12.0"
22
+ spec.add_development_dependency "rspec", "~> 3.0"
23
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "application/config"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,6 @@
1
+ {
2
+ "app":{
3
+ "user": "<%= ENV['USER'] %>"
4
+ }
5
+ }
6
+
@@ -0,0 +1,6 @@
1
+ {
2
+ "app" => {
3
+ "user" => ENV['USER'],
4
+ }
5
+ }
6
+
@@ -0,0 +1,4 @@
1
+ ---
2
+ app:
3
+ user: <%= ENV['USER'] %>
4
+
@@ -0,0 +1,18 @@
1
+ require "app/config/version"
2
+ require "app/config/base"
3
+ require "app/config/deeply"
4
+
5
+ module App
6
+ module Config
7
+ class Error < StandardError; end
8
+
9
+ class << self
10
+ include App::Config::Base
11
+ end
12
+
13
+ autoload :RUBY, "app/config/ruby"
14
+ autoload :YAML, "app/config/yaml"
15
+ autoload :JSON, "app/config/json"
16
+ end
17
+ end
18
+
@@ -0,0 +1,29 @@
1
+
2
+ module App
3
+ module Config
4
+
5
+ class Error < StandardError; end
6
+
7
+ DEFAULT_PATH = "$ROOT/config/defaults:$ROOT/config:$ROOT/var"
8
+
9
+ module Base
10
+
11
+ def new( *args, **opts )
12
+ type = args.shift || :YAML
13
+ case type.to_sym
14
+ when :RUBY
15
+ App::Config::RUBY.new( **opts )
16
+ when :YAML
17
+ App::Config::YAML.new( **opts )
18
+ when :JSON
19
+ App::Config::JSON.new( **opts )
20
+ else
21
+ raise App::Config::Error, "unknown type: #{type}"
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
29
+
@@ -0,0 +1,145 @@
1
+
2
+ ## deeply_symbolize_keys
3
+
4
+ class Hash
5
+ def deeply_symbolize_keys!
6
+ hash = self.deeply_symbolize_keys
7
+ self.clear
8
+ self.merge( hash )
9
+ end
10
+
11
+ def deeply_symbolize_keys
12
+ self.each_with_object({}) do |(key, obj), hash|
13
+ k = key.to_s.to_sym
14
+ case obj
15
+ when Hash
16
+ hash[k] = obj.deeply_symbolize_keys
17
+ else
18
+ hash[k] = obj
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+
25
+ ## deeply_stringify_keys
26
+
27
+ class Hash
28
+ def deeply_stringify_keys!
29
+ hash = self.deeply_stringify_keys
30
+ self.clear
31
+ self.merge( hash )
32
+ end
33
+
34
+ def deeply_stringify_keys
35
+ self.each_with_object({}) do |(key, obj), hash|
36
+ k = key.to_s
37
+ case obj
38
+ when Hash
39
+ hash[k] = obj.deeply_stringify_keys
40
+ else
41
+ hash[k] = obj
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+
48
+ ## deeply_merge
49
+
50
+ class Hash
51
+ def deeply_merge( hash )
52
+ self.dup.deeply_merge!( hash )
53
+ end
54
+
55
+ def deeply_merge!( hash )
56
+ raise ArgumentError("Type Invalid.") unless Hash === hash
57
+
58
+ hash.each do |key, obj|
59
+ case obj
60
+ when NilClass
61
+ self[key] = nil
62
+ when Hash
63
+ self[key] = {} if self[key].nil?
64
+ self[key].deeply_merge!(obj)
65
+ else
66
+ self[key] = obj.dup
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+
73
+ ## deeply_map
74
+
75
+ class Hash
76
+ def deeply_map( &block )
77
+ self.dup.deeply_map!( &block )
78
+ end
79
+
80
+ def deeply_map!( &block )
81
+ self.each do |key, obj|
82
+ case obj
83
+ when NilClass
84
+ self[key] = nil
85
+ when Array, Hash
86
+ self[key].deeply_map!( &block )
87
+ else
88
+ self[key] = block.call( obj )
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ class Array
95
+ def deeply_map( &block )
96
+ self.dup.deeply_map!( &block )
97
+ end
98
+
99
+ def deeply_map!( &block )
100
+ self.map! do |obj|
101
+ case obj
102
+ when NilClass
103
+ nil
104
+ when Array, Hash
105
+ obj.deeply_map!( &block )
106
+ else
107
+ block.call( obj )
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+
114
+ ## deeply_dup
115
+
116
+ class Hash
117
+ def deeply_dup
118
+ self.each_with_object({}) do |(key, obj), hash|
119
+ case obj
120
+ when NilClass
121
+ hash[key] = nil
122
+ when Array, Hash
123
+ hash[key] = obj.deeply_dup
124
+ else
125
+ hash[key] = obj.dup
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ class Array
132
+ def deeply_dup
133
+ self.map do |obj|
134
+ case obj
135
+ when NilClass
136
+ nil
137
+ when Array, Hash
138
+ obj.deeply_dup
139
+ else
140
+ obj.dup
141
+ end
142
+ end
143
+ end
144
+ end
145
+
@@ -0,0 +1,91 @@
1
+ require "fileutils"
2
+ require "erb"
3
+ require "json"
4
+ require "time"
5
+ require "date"
6
+
7
+ module App
8
+ module Config
9
+
10
+ class JSON < ::Hash
11
+ DEFAULT_MASK = "*.json"
12
+ DEFAULT_SUFFIX = ".json"
13
+
14
+ def initialize( **opts )
15
+ self.default_proc = proc do |hash, key|
16
+ hash[key] = {}
17
+ end
18
+ reload( **opts )
19
+ end
20
+
21
+ # bulk load configuration in search paths.
22
+ def reload( root: nil, path: nil, encode: nil, decode: nil )
23
+ clear
24
+ @root = root || Dir.pwd
25
+ @paths = ( path || DEFAULT_PATH ).gsub('$ROOT', @root).split(':')
26
+ @paths = @paths.map{|it| !it.nil? && !it.empty? ? it : nil}.compact
27
+ @paths << "." if @paths.empty?
28
+
29
+ @vardir = @paths.last
30
+ Dir.mkdir( @vardir ) unless ::Dir.exist?( @vardir )
31
+
32
+ @encode = { allow_nan: true }.merge( encode || {} )
33
+ @decode = { allow_nan: true }.merge( decode || {} )
34
+
35
+ load_overlay( DEFAULT_MASK )
36
+ end
37
+
38
+ # load configuration.
39
+ def load( section )
40
+ raise ArgumentError, "'#{ section }' is not String." unless String === section
41
+
42
+ self[section].clear
43
+ load_overlay( section + DEFAULT_SUFFIX )
44
+ end
45
+
46
+ # load configuration.
47
+ def load_overlay( filename )
48
+ @paths.each do |path|
49
+ begin
50
+ dirname = ::File.expand_path( path )
51
+ if ::Dir.exist?( dirname )
52
+ ::Dir.glob( "#{ dirname }/#{ filename }" ) do |pathname|
53
+ text = ::File.open( pathname ).read rescue raise( ArgumentError, "could not load #{ pathname }" )
54
+ json = ::ERB.new( text ).result rescue raise( ArgumentError, "could not parse by ERB: #{ pathname }" )
55
+ hash = ::JSON.load( json, **@decode )
56
+ self.deeply_merge!( hash )
57
+ end
58
+ end
59
+ rescue => e
60
+ STDERR.puts e.message
61
+ end
62
+ end
63
+ end
64
+
65
+ # save configuration.
66
+ def save( section )
67
+ raise ArgumentError, "'#{ section }' is not String." unless String === section
68
+ pathname = savepathname(section)
69
+ hash = { section => self[section] }.deeply_stringify_keys
70
+ ::File.open( pathname, "w" ) do |file|
71
+ file.puts( ::JSON.pretty_generate( hash, **@encode ) )
72
+ end
73
+ end
74
+
75
+ # remove and load configuration.
76
+ def reset( section )
77
+ raise ArgumentError, "'#{ section }' is not String." unless String === section
78
+
79
+ pathname = savepathname(section)
80
+ ::FileUtils.remove( pathname ) if ::File.exist?( pathname )
81
+ load( section )
82
+ end
83
+
84
+ def savepathname( section )
85
+ ::File.join( @vardir, section + DEFAULT_SUFFIX )
86
+ end
87
+
88
+ end
89
+ end
90
+ end
91
+
@@ -0,0 +1,87 @@
1
+ require "fileutils"
2
+ require "pp"
3
+
4
+ module App
5
+ module Config
6
+
7
+ class RUBY < ::Hash
8
+ DEFAULT_MASK = "*.rb"
9
+ DEFAULT_SUFFIX = ".rb"
10
+
11
+ def initialize( **opts )
12
+ self.default_proc = proc do |hash, key|
13
+ hash[key] = {}
14
+ end
15
+ reload( **opts )
16
+ end
17
+
18
+ # bulk load configuration in search paths.
19
+ def reload( root: nil, path: nil, encode: nil, decode: nil )
20
+ clear
21
+ @root = root || Dir.pwd
22
+ @paths = ( path || DEFAULT_PATH ).gsub('$ROOT', @root).split(':')
23
+ @paths = @paths.map{|it| !it.nil? && !it.empty? ? it : nil}.compact
24
+ @paths << "." if @paths.empty?
25
+
26
+ @vardir = @paths.last
27
+ Dir.mkdir( @vardir ) unless ::Dir.exist?( @vardir )
28
+
29
+ @encode = {}.merge( encode || {} )
30
+ @decode = {}.merge( decode || {} )
31
+
32
+ load_overlay( DEFAULT_MASK )
33
+ end
34
+
35
+ # load configuration.
36
+ def load( section )
37
+ raise ArgumentError, "'#{ section }' is not String." unless String === section
38
+
39
+ self[section].clear
40
+ load_overlay( section + DEFAULT_SUFFIX )
41
+ end
42
+
43
+ # load configuration.
44
+ def load_overlay( filename )
45
+ @paths.each do |path|
46
+ begin
47
+ dirname = ::File.expand_path( path )
48
+ if ::Dir.exist?( dirname )
49
+ ::Dir.glob( "#{ dirname }/#{ filename }" ) do |pathname|
50
+ text = ::File.open( pathname ).read rescue raise( ArgumentError, "could not load #{ pathname }" )
51
+ hash = eval( text )
52
+ self.deeply_merge!( hash )
53
+ end
54
+ end
55
+ rescue => e
56
+ STDERR.puts e.message
57
+ end
58
+ end
59
+ end
60
+
61
+ # save configuration.
62
+ def save( section )
63
+ raise ArgumentError, "'#{ section }' is not String." unless String === section
64
+ pathname = savepathname(section)
65
+ hash = { section => self[section] }.deeply_stringify_keys
66
+ ::File.open( pathname, "w" ) do |file|
67
+ file.puts( hash.pretty_inspect )
68
+ end
69
+ end
70
+
71
+ # remove and load configuration.
72
+ def reset( section )
73
+ raise ArgumentError, "'#{ section }' is not String." unless String === section
74
+
75
+ pathname = savepathname(section)
76
+ ::FileUtils.remove( pathname ) if ::File.exist?( pathname )
77
+ load( section )
78
+ end
79
+
80
+ def savepathname( section )
81
+ ::File.join( @vardir, section + DEFAULT_SUFFIX )
82
+ end
83
+
84
+ end
85
+ end
86
+ end
87
+
@@ -0,0 +1,5 @@
1
+ module App
2
+ module Config
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,89 @@
1
+ require "fileutils"
2
+ require "erb"
3
+ require "yaml"
4
+
5
+ module App
6
+ module Config
7
+
8
+ class YAML < ::Hash
9
+ DEFAULT_MASK = "*.{yml,yaml}"
10
+ DEFAULT_SUFFIX = ".yaml"
11
+
12
+ def initialize( **opts )
13
+ self.default_proc = proc do |hash, key|
14
+ hash[key] = {}
15
+ end
16
+ reload( **opts )
17
+ end
18
+
19
+ # bulk load configuration in search paths.
20
+ def reload( root: nil, path: nil, encode: nil, decode: nil )
21
+ clear
22
+ @root = root || Dir.pwd
23
+ @paths = ( path || DEFAULT_PATH ).gsub('$ROOT', @root).split(':')
24
+ @paths = @paths.map{|it| !it.nil? && !it.empty? ? it : nil}.compact
25
+ @paths << "." if @paths.empty?
26
+
27
+ @vardir = @paths.last
28
+ Dir.mkdir( @vardir ) unless ::Dir.exist?( @vardir )
29
+
30
+ @encode = {}.merge( encode || {} )
31
+ @decode = {}.merge( decode || {} )
32
+
33
+ load_overlay( DEFAULT_MASK )
34
+ end
35
+
36
+ # load configuration.
37
+ def load( section )
38
+ raise ArgumentError, "'#{ section }' is not String." unless String === section
39
+
40
+ self[section].clear
41
+ load_overlay( section + DEFAULT_SUFFIX )
42
+ end
43
+
44
+ # load configuration.
45
+ def load_overlay( filename )
46
+ @paths.each do |path|
47
+ begin
48
+ dirname = ::File.expand_path( path )
49
+ if ::Dir.exist?( dirname )
50
+ ::Dir.glob( "#{ dirname }/#{ filename }" ) do |pathname|
51
+ text = ::File.open( pathname ).read rescue raise( ArgumentError, "could not load #{ pathname }" )
52
+ yaml = ::ERB.new( text ).result rescue raise( ArgumentError, "could not parse by ERB: #{ pathname }" )
53
+ hash = ::YAML.load( yaml, **@decode )
54
+ self.deeply_merge!( hash )
55
+ end
56
+ end
57
+ rescue => e
58
+ STDERR.puts e.message
59
+ end
60
+ end
61
+ end
62
+
63
+ # save configuration.
64
+ def save( section )
65
+ raise ArgumentError, "'#{ section }' is not String." unless String === section
66
+ pathname = savepathname(section)
67
+ hash = { section => self[section] }.deeply_stringify_keys
68
+ ::File.open( pathname, "w" ) do |file|
69
+ file.puts( ::YAML.dump( hash, **@encode ) )
70
+ end
71
+ end
72
+
73
+ # remove and load configuration.
74
+ def reset( section )
75
+ raise ArgumentError, "'#{ section }' is not String." unless String === section
76
+
77
+ pathname = savepathname(section)
78
+ ::FileUtils.remove( pathname ) if ::File.exist?( pathname )
79
+ load( section )
80
+ end
81
+
82
+ def savepathname( section )
83
+ ::File.join( @vardir, section + DEFAULT_SUFFIX )
84
+ end
85
+
86
+ end
87
+ end
88
+ end
89
+
@@ -0,0 +1,24 @@
1
+ require "app/config"
2
+
3
+ path = "$ROOT/config/defaults/:$ROOT/config:$ROOT/var"
4
+
5
+ # initialize variation
6
+
7
+ pp config = App::Config.new
8
+ pp config = App::Config.new( root: Dir.pwd )
9
+ pp config = App::Config.new( path: path )
10
+
11
+ pp config = App::Config.new( :YAML )
12
+ pp config = App::Config.new( "YAML" )
13
+ pp config = App::Config.new( :YAML, path: path )
14
+ pp config = App::Config.new( "YAML", path: path )
15
+ pp config = App::Config::YAML.new
16
+ pp config = App::Config::YAML.new( path: path )
17
+
18
+ pp config = App::Config.new( :JSON )
19
+ pp config = App::Config.new( "JSON" )
20
+ pp config = App::Config.new( :JSON, path: path )
21
+ pp config = App::Config.new( "JSON", path: path )
22
+ pp config = App::Config::JSON.new
23
+ pp config = App::Config::JSON.new( path: path )
24
+
@@ -0,0 +1,20 @@
1
+ require "app/config"
2
+
3
+ path = "$ROOT/config/defaults/:$ROOT/config:$ROOT/var"
4
+
5
+ type = ARGV.shift || :YAML
6
+ config = App::Config.new(type)
7
+
8
+ pp config.class
9
+ pp config.keys
10
+ pp config
11
+
12
+ config.reload
13
+ config.reload( path: path )
14
+ config.load("section")
15
+
16
+ value = config["section"]["seqn"].to_i
17
+ p ["seqn", value]
18
+ config["section"]["seqn"] = value + 1
19
+ config.save("section")
20
+
@@ -0,0 +1,21 @@
1
+ require "app/config"
2
+ require "time"
3
+
4
+ type = ARGV.shift || :YAML
5
+
6
+ # initialize object, load and merge all sections.
7
+ config = App::Config.new(type)
8
+
9
+ # save section
10
+ config["status"]["lastdate"] = Time.now.iso8601(3)
11
+ config.save("status")
12
+
13
+ # show section
14
+ pp config["status"]
15
+
16
+ # debug print
17
+ Dir.glob("var/*.#{type.to_s.downcase}") do |pathname|
18
+ p pathname
19
+ puts open(pathname).read
20
+ end
21
+
@@ -0,0 +1,10 @@
1
+ require "app/config"
2
+
3
+ type = ARGV.shift || :YAML
4
+
5
+ # initialize object, load and merge all sections.
6
+ config = App::Config.new(type)
7
+
8
+ # remove and reload section
9
+ config.reset("status")
10
+
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: app-configs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - arimay
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-10-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '12.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '12.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ description: " Yet another library for load/save app config files. "
42
+ email:
43
+ - arima.yasuhiro@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".rspec"
50
+ - ".travis.yml"
51
+ - Gemfile
52
+ - README.adoc
53
+ - README.ja.adoc
54
+ - Rakefile
55
+ - app-configs.gemspec
56
+ - bin/console
57
+ - bin/setup
58
+ - config/app.json
59
+ - config/app.rb
60
+ - config/app.yaml
61
+ - lib/app/config.rb
62
+ - lib/app/config/base.rb
63
+ - lib/app/config/deeply.rb
64
+ - lib/app/config/json.rb
65
+ - lib/app/config/ruby.rb
66
+ - lib/app/config/version.rb
67
+ - lib/app/config/yaml.rb
68
+ - sample/sample_1.rb
69
+ - sample/sample_2.rb
70
+ - sample/sample_3.rb
71
+ - sample/sample_4.rb
72
+ homepage: https://github.com/arimay/app-configs
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubygems_version: 3.1.4
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Application config loader/saver.
95
+ test_files: []