mimi-config 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cca2e6a1670a7c4f5721347e52617840139f84c3
4
- data.tar.gz: 744fb11b98ed3ddbb7524a73a0a58b8156b0ddb7
3
+ metadata.gz: c11b17f051b8f15e08c1a3fbcfe0ba385949ff4a
4
+ data.tar.gz: 1c9eea0c84229415e795cfe45d107500f249250d
5
5
  SHA512:
6
- metadata.gz: 8c7b0f8d48b89bfa92f24aea94ab620a692d8b67bc170bc89f1f75f0b2264cf2cdcfd82d06732681cff6c9f4527373f1be51448de19164d5eb9977848bca2a97
7
- data.tar.gz: 4181ee303e70a2751fe026d89b639afc28ba6384e795f9f0f6c231dc855f4152b1ff63ea9cc023823bc855f51679fcabcfae35db82e4d29605acb229038fa5e9
6
+ metadata.gz: f6774639e0cd68abc8d81b44ede677827f42c933063bd93af2a811bce0dd17596fce9923c42bb235059ec24aaa022cd0f406edb5d98be27da98cc25797243fa2
7
+ data.tar.gz: 77b66fe00e50c047ed8314cf9c05cf713114368769b57d252ccd7f928bd243524359700ed2e607159f257b7b1f94083b5d34564c3a388b4399376980f5645a3d
data/Gemfile CHANGED
@@ -3,4 +3,5 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  # Comment out the following gem instructions, if you not using gem sources
6
- # gem 'mimi-core', path: '/mimi-core'
6
+ gem 'mimi-core', path: '../mimi-core'
7
+
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # mimi-config
2
2
 
3
- A simple ENV based configuration for microservice applications.
3
+ A simple ENV and manifest based configuration for microservice applications.
4
4
 
5
5
 
6
6
  ## Installation
@@ -23,64 +23,196 @@ Or install it yourself as:
23
23
 
24
24
  `Mimi::Config` allows you to define a set of configurable parameters and constants in a *manifest* file with a simple YAML format.
25
25
 
26
+ When instantiated, a `Mimi::Config` object reads and parses the manifest found in the specified file,
27
+ loads parameter values from ENV variables and processes them according to the manifest.
28
+
29
+ On success, `Mimi::Config` object makes configurable parameters available as Hash keys
30
+ or as methods:
31
+
32
+ ```yaml
33
+ # manifest.yml
34
+ param1:
35
+ default: "foobar"
36
+ ```
37
+
38
+ ```ruby
39
+ require 'mimi/config'
40
+
41
+ config = Mimi::Config.new('manifest.yml')
42
+ config.param1 # => "foobar", if ENV['param1'] is not set
43
+ ```
44
+
45
+
46
+ ## Manifest
47
+
48
+ A *manifest* is a formal declaration of accepted configurable parameters.
49
+ Only the parameters defined in the manifest may be set.
50
+
51
+ For each configurable parameter there may be declared:
52
+
53
+ * configurable parameter name
54
+ * human readable description of the parameter
55
+ * type of accepted values
56
+ * default value
57
+ * whether this parameter is constant or not
58
+
26
59
  ### Example manifest.yml
27
60
  ```yaml,name=manifest.yml
61
+ # This is a minimal definition of a configurable parameter.
62
+ # Its type is 'string', there is no human readable description and no default value:
63
+ min1:
64
+
65
+ # This parameter is optional as it has a default value.
28
66
  opt1:
29
67
  desc: This is an optional configurable parameter
30
- default: 123
68
+ default: "opt1.default"
31
69
 
70
+ # Having no defined default value makes the configurable parameter required
71
+ req1:
72
+ desc: This is a required configurable parameter
73
+
74
+ # An optional configurable parameter with a default value of 'nil':
32
75
  opt2:
33
- desc: This is an optional configurable parameter with the default value of nil
34
76
  default:
35
77
 
78
+ # A constant parameter of type 'string'.
79
+ # It must have a default value and it cannot be changed via ENV variable.
36
80
  const1:
37
- desc: This is a constant parameter, that cannot be changed via an ENV variable
38
- const: 456
81
+ desc: This is a constant parameter
82
+ default: "const1.default"
83
+ const: true
84
+ ```
85
+
86
+ ### Configurable parameter types
39
87
 
88
+ The type of configurable parameter defines which values/format it accepts from ENV,
89
+ and the type it converts the processed value to.
40
90
 
41
- req1: This is a required configurable parameter
91
+ ```yaml
92
+ # manifest_with_types.yml
42
93
 
43
- req2:
44
- desc: And so is this one
94
+ # 'string' accepts any value and converts to String
95
+ str1:
96
+ type: string
45
97
 
46
- # And so is this one with no description
47
- req3:
98
+ # 'integer' accepts any positive integer and converts to Integer
99
+ int1:
100
+ type: integer
101
+
102
+ # 'decimal' accepts a decimal number representation (integer or fractional) and converts to BigDecimal
103
+ dec1:
104
+ type: decimal
105
+
106
+ # 'boolean' accepts only String values 'true' and 'false',
107
+ # and converts to Ruby literals 'true' or 'false'.
108
+ bool1:
109
+ type: boolean
110
+
111
+ # 'json' accepts a valid JSON and converts to a decoded object (of any type)
112
+ json1:
113
+ type: json
114
+
115
+ # 'enum' is a special type that accepts only values from a provided set of string literals.
116
+ # Converts the value to String.
117
+ enum1:
118
+ type:
119
+ - debug
120
+ - info
121
+ - warn
122
+ - error
48
123
  ```
49
124
 
125
+ **Example:**
126
+
127
+ ```ruby
128
+ require 'mimi/config'
129
+
130
+ # Provided the ENV values are set as:
131
+ ENV['str1'] # => "foobar"
132
+ ENV['int1'] # => "123"
133
+ ENV['dec1'] # => "1.23"
134
+ ENV['bool1'] # => "true"
135
+ ENV['json1'] # => "[{\"a\":1},{\"b\":2}]"
136
+ ENV['enum1'] # => "info"
137
+
138
+ config = Mimi::Config.new('manifest_with_types.yml')
139
+
140
+ config.str1 # => "foobar" (String)
141
+ config.int1 # => 123 (Integer)
142
+ config.dec1 # => 1.23 (BigDecimal)
143
+ config.bool1 # => true (TrueClass)
144
+ config.json1 # => [{"a"=>1}, {"b"=>2}] (Array)
145
+ config.enum1 # => "info" (String)
146
+ ```
147
+
148
+
50
149
  ### How to load configuration from your app
51
150
 
52
151
  Providing you have placed your manifest into `config/manifest.yml`:
53
152
 
153
+ ```yaml
154
+ const1:
155
+ default: 456
156
+ const: true
157
+
158
+ req1:
159
+
160
+ opt1:
161
+ default: foobar
162
+
163
+ opt2:
164
+ type: integer
165
+ default: 0
166
+ ```
167
+
54
168
  ```ruby
55
169
  config = Mimi::Config.new('config/manifest.yml')
56
170
 
57
171
  config.const1 # => 456, from manifest.yml
58
- config.opt1 # value from ENV['opt1'] or default from manifest.yml
172
+ config.opt1 # value from ENV['opt1'] or default "foobar" from manifest.yml
59
173
  config.req2 # value from ENV['req2']
60
174
 
61
175
  # alternatively use [] syntax:
62
176
  config.opt2 #
63
- config[:opt2] # all three refer to the same configurable parameter
64
- config['opt2'] #
177
+ config[:opt2] # refers to the same configurable parameter
65
178
 
66
179
  # you cannot access parameters not defined in the manifest:
67
- config.req5 # => NoMethodError
68
- config['req5'] # => ArgumentError
180
+ config.foobar # => NoMethodError
181
+ config[:foobar] # => ArgumentError
182
+
183
+ # when using [] syntax, use Symbol as parameter name:
184
+ config.opt2 # => 0, if ENV['opt2'] is not set
185
+ config[:opt2] # => 0, if ENV['opt2'] is not set
186
+ config['opt2'] # => ArgumentError
69
187
 
70
188
  # check, if parameter is defined:
71
- config.include?('req5') # => false
189
+ config.include?(:foobar) # => false
72
190
  ```
73
191
 
74
- ## Development
192
+ ### Using with Dotenv
193
+
194
+ When a `Mimi::Config` object is instantiated, the `.env` file is loaded and processed,
195
+ the functionality provided by the `dotenv` gem.
196
+
197
+ You can choose to disable `dotenv` and `.env` file loading:
198
+
199
+ ```ruby
200
+ require 'mimi/config'
75
201
 
76
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
202
+ config = Mimi::Config.new('manifest.yml', config_use_dotenv: false)
203
+ ```
77
204
 
78
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
205
+ ### Using as Mimi component
79
206
 
80
- ## Contributing
207
+ It is possible to configure `Mimi::Config` as a Mimi module:
81
208
 
82
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/mimi-config. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
209
+ ```ruby
210
+ require 'mimi/config'
211
+
212
+ Mimi.use Mimi::Config, config_use_dotenv: false
213
+ ```
83
214
 
215
+ After that, any `Mimi::Config` object you instantiate will use provided options as default.
84
216
 
85
217
  ## License
86
218
 
@@ -1,5 +1,5 @@
1
1
  module Mimi
2
2
  class Config
3
- VERSION = '0.1.1'.freeze
3
+ VERSION = '1.0.0'.freeze
4
4
  end # class Config
5
5
  end # module Mimi
data/lib/mimi/config.rb CHANGED
@@ -22,10 +22,30 @@ module Mimi
22
22
  # Current set of values for configurable and const parameters
23
23
  attr_reader :params
24
24
 
25
- default_options(
26
- raise_on_missing_params: true,
27
- use_dotenv: true
28
- )
25
+ # Mimi::Config module manifest
26
+ #
27
+ def self.manifest
28
+ {
29
+ config_raise_on_missing_params: {
30
+ desc: 'Raise error on missing params',
31
+ default: true,
32
+ hidden: true
33
+ },
34
+ config_use_dotenv: {
35
+ desc: 'Use Dotenv and load .env file',
36
+ default: true,
37
+ hidden: true
38
+ }
39
+ }
40
+ end
41
+
42
+ # Returns the module path, for exported rake files
43
+ #
44
+ # @return [Pathname]
45
+ #
46
+ def self.module_path
47
+ Pathname.new(__dir__).join('..', '..').expand_path
48
+ end
29
49
 
30
50
  # Creates a Config object.
31
51
  #
@@ -37,7 +57,7 @@ module Mimi
37
57
  # @param manifest_filename [String,nil] path to the manifest.yml or nil to skip loading manifest
38
58
  #
39
59
  def initialize(manifest_filename = nil, opts = {})
40
- @manifest = Mimi::Config::Manifest.new
60
+ @manifest = Mimi::Core::Manifest.new({})
41
61
  @params = {}
42
62
  load(manifest_filename, opts) if manifest_filename
43
63
  end
@@ -46,11 +66,11 @@ module Mimi
46
66
  # from ENV.
47
67
  #
48
68
  def load(manifest_filename, opts = {})
49
- opts = self.class.module_options.deep_merge(opts)
69
+ opts = self.class.options.deep_merge(opts)
50
70
  manifest_filename = Pathname.new(manifest_filename).expand_path
51
- load_manifest(manifest_filename, opts)
71
+ @manifest.merge!(self.class.load_manifest(manifest_filename, opts))
52
72
  load_params(opts)
53
- if opts[:raise_on_missing_params] && !missing_params.empty?
73
+ if opts[:config_raise_on_missing_params] && !missing_params.empty?
54
74
  raise "Missing required configurable parameters: #{missing_params.join(', ')}"
55
75
  end
56
76
  self
@@ -63,23 +83,11 @@ module Mimi
63
83
  required_params - @params.keys
64
84
  end
65
85
 
66
- # Returns annotated manifest
86
+ # Returns the underlying manifest
67
87
  #
68
- def manifest
69
- @manifest.map do |k, v|
70
- {
71
- name: k,
72
- desc: v[:desc],
73
- required: !v.key?(:default),
74
- const: v[:const],
75
- default: v[:default]
76
- }
77
- end
78
- end
79
-
80
- # Returns raw manifest
88
+ # @return [Mimi::Core::Manifest]
81
89
  #
82
- def manifest_raw
90
+ def manifest
83
91
  @manifest
84
92
  end
85
93
 
@@ -89,26 +97,29 @@ module Mimi
89
97
  # via #[] and #<name> methods.
90
98
  #
91
99
  def include?(name)
92
- @manifest.key?(name.to_sym)
100
+ @manifest.to_h.key?(name.to_sym)
93
101
  end
94
102
 
95
103
  # Returns the parameter value
96
104
  #
97
- # @param key [String,Symbol] parameter name
105
+ # @param key [Symbol] parameter name
98
106
  #
99
107
  def [](key)
108
+ unless key.is_a?(Symbol)
109
+ raise ArgumentError, "Invalid key to #[], Symbol expected: '#{key.inspect}'"
110
+ end
100
111
  raise ArgumentError, "Undefined parameter '#{key}'" unless include?(key)
101
- @params[key.to_sym]
112
+ @params[key]
102
113
  end
103
114
 
104
115
  # Provides access to parameters as methods.
105
116
  #
106
117
  # Example:
107
- # config['foo'] # => 'bar'
118
+ # config[:foo] # => 'bar'
108
119
  # config.foo # => 'bar'
109
120
  #
110
121
  # # missing parameter
111
- # config['bar'] # => ArgumentError
122
+ # config[:bar] # => ArgumentError
112
123
  # config.bar # => NoMethodError
113
124
  #
114
125
  def method_missing(name, *)
@@ -126,46 +137,40 @@ module Mimi
126
137
  # @return [Hash]
127
138
  #
128
139
  def to_h
129
- @manifest.keys.map do |k|
140
+ @manifest.to_h.keys.map do |k|
130
141
  [k, self[k]]
131
142
  end.to_h
132
143
  end
133
144
 
134
145
  # Returns to_h.to_s
135
146
  #
147
+ # @return [String]
148
+ #
136
149
  def to_s
137
150
  to_h.to_s
138
151
  end
139
152
 
140
- private
141
-
142
- # Reads manifest file and merges it with the current manifest.
153
+ # Reads and parses the manifest file and constructs the Mimi::Core::Manifest object
154
+ #
155
+ # @param filename [Pathname]
156
+ # @param _opts
157
+ # @return [Mimi::Core::Manifest]
143
158
  #
144
- def load_manifest(filename, _opts = {})
145
- @manifest.load(filename)
159
+ def self.load_manifest(filename, _opts = {})
160
+ Mimi::Core::Manifest.from_yaml(File.read(filename))
161
+ rescue StandardError => e
162
+ raise "Failed to load config manifest from '#{filename}': #{e}"
146
163
  end
147
164
 
165
+ private
166
+
148
167
  # Reads parameters from the ENV according to the current manifest
149
168
  #
150
169
  def load_params(opts = {})
151
- Dotenv.load if opts[:use_dotenv]
152
- manifest.each do |p|
153
- env_name = p[:name].to_s
154
- if p[:const]
155
- # const
156
- @params[p[:name]] = p[:default]
157
- elsif p[:required]
158
- # required configurable
159
- @params[p[:name]] = ENV[env_name] if ENV.key?(env_name)
160
- else
161
- # optional configurable
162
- @params[p[:name]] = ENV.key?(env_name) ? ENV[env_name] : p[:default]
163
- end
164
- end
165
- @params
170
+ Dotenv.load if opts[:config_use_dotenv]
171
+ @params = @manifest.apply(ENV.to_h.symbolize_keys)
166
172
  end
167
173
  end # class Config
168
174
  end # module Mimi
169
175
 
170
176
  require_relative 'config/version'
171
- require_relative 'config/manifest'
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Returns the path to the manifest file
4
+ #
5
+ # @return [Pathname]
6
+ #
7
+ def rake_task_config_manifest_filename
8
+ Mimi.app_path_to('config', 'manifest.yml')
9
+ end
10
+
11
+ # Displays current manifest and configured values in .env format
12
+ #
13
+ # @param include_consts [true,false] include non-configurable parameters (consts)
14
+ #
15
+ def rake_task_config(include_consts = false)
16
+ manifest = Mimi::Config.load_manifest(rake_task_config_manifest_filename)
17
+ missing_params = manifest.keys.select { |k| manifest.required?(k) }.reject { |k| ENV.key?(k.to_s) }
18
+
19
+ manifest.to_h.each do |name, props|
20
+ next if props[:const] && !include_consts
21
+ annotation = []
22
+ if props[:const]
23
+ annotation << '[CONST]'
24
+ annotation << "(value: #{props[:default].inspect})"
25
+ elsif missing_params.include?(name)
26
+ annotation << "[MISSING] (#{props[:type]})"
27
+ else
28
+ annotation << "(#{props[:type]}, default: #{props[:default].inspect})"
29
+ end
30
+ annotation << props[:desc] if props.key?(:desc)
31
+ annotation.unshift(' #') unless annotation.empty?
32
+ puts "#{name}=#{ENV[name.to_s]}#{annotation.join(' ')}"
33
+ end
34
+ abort('# FIXME: configure missing parameters') unless missing_params.empty?
35
+ end
36
+
37
+ # Generates a new/updated config manifest
38
+ #
39
+ # @return [String] a config manifest in the YAML format
40
+ #
41
+ def rake_task_config_manifest_generate
42
+ manifest = Mimi::Core::Manifest.new({})
43
+
44
+ # merge loaded modules manifests
45
+ Mimi.loaded_modules.map(&:manifest).each do |manifest_hash|
46
+ manifest.merge!(manifest_hash)
47
+ end
48
+
49
+ # merge app's explicit manifest
50
+ app_manifest = Mimi::Config.load_manifest(rake_task_config_manifest_filename)
51
+ manifest.merge!(app_manifest)
52
+
53
+ manifest.to_yaml
54
+ end
55
+
56
+ desc 'Display config manifest and current config'
57
+ task :config do
58
+ rake_task_config(false)
59
+ end
60
+
61
+ namespace :config do
62
+ desc 'Display config manifest and current config, including consts'
63
+ task :all do
64
+ rake_task_config(true)
65
+ end
66
+
67
+ desc 'Generate and display a combined manifest for all loaded modules'
68
+ task :manifest do
69
+ puts rake_task_config_manifest_generate
70
+ end
71
+
72
+ namespace :manifest do
73
+ manifest_filename = Pathname.pwd.join('config', 'manifest.yml')
74
+ desc "Generate and write a combined manifest to: #{manifest_filename}"
75
+ task :create do
76
+ if File.exist?(manifest_filename)
77
+ puts "* Found an existing application manifest, loading: #{manifest_filename}"
78
+ end
79
+ puts '* Generating a combined manifest'
80
+ manifest_contents = rake_task_config_manifest_generate
81
+ config_path = Mimi.app_path_to('config')
82
+ puts "* Writing the combined manifest to: #{manifest_filename}"
83
+ sh "install -d #{config_path}" unless File.directory?(config_path)
84
+ File.open(rake_task_config_manifest_filename, 'w') do |f|
85
+ f.puts manifest_contents
86
+ end
87
+ end
88
+ end
89
+ end
data/mimi-config.gemspec CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ['lib']
29
29
 
30
- spec.add_dependency 'mimi-core', '~> 0.1'
30
+ spec.add_dependency 'mimi-core', '~> 1.0'
31
31
  spec.add_dependency 'dotenv', '~> 2.1'
32
32
 
33
33
  spec.add_development_dependency 'bundler', '~> 1.11'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mimi-config
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Kukushkin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-09 00:00:00.000000000 Z
11
+ date: 2019-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mimi-core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.1'
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.1'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: dotenv
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -112,8 +112,8 @@ files:
112
112
  - bin/console
113
113
  - bin/setup
114
114
  - lib/mimi/config.rb
115
- - lib/mimi/config/manifest.rb
116
115
  - lib/mimi/config/version.rb
116
+ - lib/tasks/config.rake
117
117
  - mimi-config.gemspec
118
118
  homepage: https://github.com/kukushkin/mimi-config
119
119
  licenses:
@@ -136,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
136
  version: '0'
137
137
  requirements: []
138
138
  rubyforge_project:
139
- rubygems_version: 2.4.5.1
139
+ rubygems_version: 2.6.14.4
140
140
  signing_key:
141
141
  specification_version: 4
142
142
  summary: Simple ENV based configuration for microservice apps
@@ -1,86 +0,0 @@
1
- module Mimi
2
- class Config
3
- class Manifest < Hash
4
- # Reads manifest file and merges it with the current manifest.
5
- #
6
- # @return [Mimi::Config::Manifest] current manifest merged with the new one
7
- #
8
- def load(filename_or_hash, _opts = {})
9
- new_manifest = nil
10
- if filename_or_hash.is_a?(String) || filename_or_hash.is_a?(Pathname)
11
- new_manifest = YAML.load(File.read(filename_or_hash))
12
- end
13
- new_manifest = filename_or_hash.dup if filename_or_hash.is_a?(Hash)
14
- return self unless new_manifest
15
- raise 'Invalid manifest file format' unless new_manifest.is_a?(Hash)
16
- new_manifest.each do |k, v|
17
- merge_key(k, v)
18
- end
19
- self
20
- rescue StandardError => e
21
- raise "Failed to load manifest file: #{e}"
22
- end
23
-
24
- # Returns YAML representation of the manifest
25
- #
26
- # @return [String]
27
- #
28
- def to_yaml
29
- out = []
30
- self.each do |k, v|
31
- if v.key?(:const)
32
- out << "#{k}:"
33
- out << " desc: #{value_to_yaml(v[:desc])}" if v.key?(:desc)
34
- if v[:const]
35
- out << " const: #{value_to_yaml(v[:default])}"
36
- elsif v.key?(:default)
37
- out << " default: #{value_to_yaml(v[:default])}"
38
- end
39
- elsif v.key?(:desc)
40
- out << "#{k}: #{value_to_yaml(v[:desc])}"
41
- else
42
- out << "#{k}:"
43
- end
44
- out << ''
45
- end
46
- out.join("\n")
47
- end
48
-
49
- private
50
-
51
- def value_to_yaml(v)
52
- v.nil? ? '# nil' : v.inspect
53
- end
54
-
55
- def merge_key(k, v)
56
- k = k.to_sym
57
- self[k] ||= {}
58
- if v.nil?
59
- # var:
60
- elsif v.is_a?(String)
61
- # var: A description
62
- self[k][:desc] = v
63
- elsif v.is_a?(Hash)
64
- merge_key_hash(k, v)
65
- end
66
- end
67
-
68
- def merge_key_hash(k, v)
69
- v = v.dup.stringify_keys
70
- self[k][:desc] = v['desc'] if v.key?('desc')
71
-
72
- if v.key?('const') && v.key?('default')
73
- raise "Invalid mix of 'const' and 'default' in parameter definition '#{k}'"
74
- end
75
-
76
- if v.key?('default')
77
- self[k][:const] = false
78
- self[k][:default] = v['default']
79
- elsif v.key?('const')
80
- self[k][:const] = true
81
- self[k][:default] = v['const']
82
- end
83
- end
84
- end # class Manifest
85
- end # class Config
86
- end # module Mimi