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.
@@ -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: []