app-configs 0.1.0
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 +23 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +5 -0
- data/README.adoc +153 -0
- data/README.ja.adoc +153 -0
- data/Rakefile +96 -0
- data/app-configs.gemspec +23 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config/app.json +6 -0
- data/config/app.rb +6 -0
- data/config/app.yaml +4 -0
- data/lib/app/config.rb +18 -0
- data/lib/app/config/base.rb +29 -0
- data/lib/app/config/deeply.rb +145 -0
- data/lib/app/config/json.rb +91 -0
- data/lib/app/config/ruby.rb +87 -0
- data/lib/app/config/version.rb +5 -0
- data/lib/app/config/yaml.rb +89 -0
- data/sample/sample_1.rb +24 -0
- data/sample/sample_2.rb +20 -0
- data/sample/sample_3.rb +21 -0
- data/sample/sample_4.rb +10 -0
- metadata +95 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
@@ -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
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.adoc
ADDED
@@ -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>
|
data/README.ja.adoc
ADDED
@@ -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>
|
data/Rakefile
ADDED
@@ -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
|
+
|
data/app-configs.gemspec
ADDED
@@ -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
|
data/bin/console
ADDED
@@ -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__)
|
data/bin/setup
ADDED
data/config/app.json
ADDED
data/config/app.rb
ADDED
data/config/app.yaml
ADDED
data/lib/app/config.rb
ADDED
@@ -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,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
|
+
|
data/sample/sample_1.rb
ADDED
@@ -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
|
+
|
data/sample/sample_2.rb
ADDED
@@ -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
|
+
|
data/sample/sample_3.rb
ADDED
@@ -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
|
+
|
data/sample/sample_4.rb
ADDED
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: []
|