app-configs 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|