configliere 0.3.4 → 0.4.4
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.
- data/.document +3 -0
- data/.watchr +20 -0
- data/CHANGELOG.textile +99 -3
- data/Gemfile +26 -0
- data/Gemfile.lock +54 -0
- data/README.textile +162 -138
- data/Rakefile +30 -21
- data/VERSION +1 -1
- data/bin/configliere +77 -77
- data/bin/configliere-decrypt +85 -0
- data/bin/configliere-delete +85 -0
- data/bin/configliere-dump +85 -0
- data/bin/configliere-encrypt +85 -0
- data/bin/configliere-list +85 -0
- data/bin/configliere-set +85 -0
- data/configliere.gemspec +53 -23
- data/examples/config_block_script.rb +9 -2
- data/examples/encrypted_script.rb +28 -16
- data/examples/env_var_script.rb +2 -2
- data/examples/help_message_demo.rb +16 -0
- data/examples/independent_config.rb +28 -0
- data/examples/prompt.rb +23 -0
- data/examples/simple_script.rb +28 -15
- data/examples/simple_script.yaml +1 -1
- data/lib/configliere.rb +22 -24
- data/lib/configliere/commandline.rb +135 -116
- data/lib/configliere/commands.rb +38 -54
- data/lib/configliere/config_block.rb +4 -2
- data/lib/configliere/config_file.rb +30 -52
- data/lib/configliere/crypter.rb +8 -5
- data/lib/configliere/deep_hash.rb +368 -0
- data/lib/configliere/define.rb +83 -89
- data/lib/configliere/encrypted.rb +17 -18
- data/lib/configliere/env_var.rb +5 -7
- data/lib/configliere/param.rb +37 -64
- data/lib/configliere/prompt.rb +23 -0
- data/spec/configliere/commandline_spec.rb +156 -57
- data/spec/configliere/commands_spec.rb +75 -30
- data/spec/configliere/config_block_spec.rb +10 -1
- data/spec/configliere/config_file_spec.rb +83 -55
- data/spec/configliere/crypter_spec.rb +3 -2
- data/spec/configliere/deep_hash_spec.rb +401 -0
- data/spec/configliere/define_spec.rb +121 -42
- data/spec/configliere/encrypted_spec.rb +53 -20
- data/spec/configliere/env_var_spec.rb +24 -4
- data/spec/configliere/param_spec.rb +25 -27
- data/spec/configliere/prompt_spec.rb +50 -0
- data/spec/configliere_spec.rb +3 -9
- data/spec/spec_helper.rb +17 -6
- metadata +110 -35
- data/lib/configliere/core_ext.rb +0 -2
- data/lib/configliere/core_ext/blank.rb +0 -93
- data/lib/configliere/core_ext/hash.rb +0 -108
- data/lib/configliere/core_ext/sash.rb +0 -170
- data/spec/configliere/core_ext/hash_spec.rb +0 -78
- data/spec/configliere/core_ext/sash_spec.rb +0 -312
data/lib/configliere/define.rb
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
module Configliere
|
2
2
|
module Define
|
3
|
-
# Definitions for params: :description, :type, :encrypted, etc.
|
4
|
-
attr_writer :param_definitions
|
5
3
|
|
4
|
+
# Define arbitrary attributes of a param, notably:
|
5
|
+
#
|
6
|
+
# [:description] Documentation for the param, used in the --help message
|
7
|
+
# [:default] Sets a default value (applied immediately)
|
8
|
+
# [:env_var] Environment variable to adopt (applied immediately, and after +:default+)
|
9
|
+
# [:encrypted] Obscures/Extracts the contents of this param when serialized
|
10
|
+
# [:type] Converts param's value to the given type, just before the finally block is called
|
11
|
+
# [:finally] Block of code to postprocess settings or handle complex configuration.
|
12
|
+
# [:required] Raises an error if, at the end of calling resolve!, the param's value is nil.
|
13
|
+
#
|
6
14
|
# @param param the setting to describe. Either a simple symbol or a dotted param string.
|
7
15
|
# @param definitions the defineables to set (:description, :type, :encrypted, etc.)
|
8
16
|
#
|
@@ -10,30 +18,28 @@ module Configliere
|
|
10
18
|
# Settings.define :dest_time, :type => Date, :description => 'Arrival time. If only a date is given, the current time of day on that date is assumed.'
|
11
19
|
# Settings.define 'delorean.power_source', :description => 'Delorean subsytem supplying power to the Flux Capacitor.'
|
12
20
|
# Settings.define :password, :required => true, :obscure => true
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
self.use(:
|
19
|
-
self
|
20
|
-
self.
|
21
|
-
self
|
21
|
+
# Settings.define :danger, :finally => lambda{|c| if c[:delorean][:power_source] == 'plutonium' than c.danger = 'high' }
|
22
|
+
#
|
23
|
+
def define param, pdefs={}, &block
|
24
|
+
param = param.to_sym
|
25
|
+
definitions[param].merge! pdefs
|
26
|
+
self.use(:env_var) if pdefs.include?(:env_var)
|
27
|
+
self.use(:encrypted) if pdefs.include?(:encrypted)
|
28
|
+
self.use(:config_block) if pdefs.include?(:finally)
|
29
|
+
self[param] = pdefs[:default] if pdefs.include?(:default)
|
30
|
+
self.env_vars param => pdefs[:env_var] if pdefs.include?(:env_var)
|
31
|
+
self.finally(&pdefs[:finally]) if pdefs.include?(:finally)
|
22
32
|
self.finally(&block) if block
|
23
33
|
end
|
24
34
|
|
25
|
-
|
26
|
-
# initialize the param_definitions as an auto-vivifying hash if it's never been set
|
27
|
-
@param_definitions ||= Sash.new{|hsh, key| hsh[key] = Sash.new }
|
28
|
-
end
|
29
|
-
|
30
|
-
# performs type coercion
|
35
|
+
# performs type coercion, continues up the resolve! chain
|
31
36
|
def resolve!
|
32
37
|
resolve_types!
|
33
38
|
super()
|
34
39
|
self
|
35
40
|
end
|
36
41
|
|
42
|
+
# ensures required types are defined, continues up the validate! chain
|
37
43
|
def validate!
|
38
44
|
validate_requireds!
|
39
45
|
super()
|
@@ -42,25 +48,55 @@ module Configliere
|
|
42
48
|
|
43
49
|
# ===========================================================================
|
44
50
|
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
# Settings.define :param, :description => '...'
|
51
|
+
# Helpers for retrieving definitions
|
48
52
|
#
|
49
53
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
param_definitions[param][:description]
|
54
|
+
private
|
55
|
+
def definitions
|
56
|
+
@definitions ||= Hash.new{|hsh, key| hsh[key.to_sym] = Hash.new }
|
54
57
|
end
|
58
|
+
public
|
55
59
|
|
56
|
-
#
|
57
|
-
def
|
58
|
-
|
60
|
+
# Is the param defined?
|
61
|
+
def has_definition? param
|
62
|
+
definitions.has_key?(param.to_sym)
|
63
|
+
end
|
64
|
+
|
65
|
+
# all params with a value for the given aspect
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# @config.define :has_description, :description => 'desc 1', :foo => 'bar'
|
69
|
+
# #
|
70
|
+
# definition_of(:has_description)
|
71
|
+
# # => {:description => 'desc 1', :foo => 'bar'}
|
72
|
+
# definition_of(:has_description, :description)
|
73
|
+
# # => 'desc 1'
|
74
|
+
#
|
75
|
+
# @param aspect [Symbol] the aspect to list (:description, :type, :encrypted, etc.)
|
76
|
+
# @return [Hash, Object]
|
77
|
+
def definition_of(param, attr=nil)
|
78
|
+
attr ? definitions[param.to_sym][attr] : definitions[param.to_sym]
|
59
79
|
end
|
60
80
|
|
61
|
-
#
|
62
|
-
|
63
|
-
|
81
|
+
# a hash holding every param with that aspect and its definition
|
82
|
+
#
|
83
|
+
# @example
|
84
|
+
# @config.define :has_description, :description => 'desc 1'
|
85
|
+
# @config.define :also_has_description, :description => 'desc 2'
|
86
|
+
# @config.define :no_description, :something_else => 'foo'
|
87
|
+
# #
|
88
|
+
# params_with(:description)
|
89
|
+
# # => { :has_description => 'desc 1', :also_has_description => 'desc 2' }
|
90
|
+
#
|
91
|
+
# @param aspect [Symbol] the aspect to list (:description, :type, :encrypted, etc.)
|
92
|
+
# @return [Hash]
|
93
|
+
def params_with(aspect)
|
94
|
+
hsh = {}
|
95
|
+
definitions.each do |param_name, param_def|
|
96
|
+
next unless param_def.has_key?(aspect)
|
97
|
+
hsh[param_name] = definition_of(param_name, aspect)
|
98
|
+
end
|
99
|
+
hsh
|
64
100
|
end
|
65
101
|
|
66
102
|
# ===========================================================================
|
@@ -72,44 +108,28 @@ module Configliere
|
|
72
108
|
# Settings.define :param, :type => Date
|
73
109
|
#
|
74
110
|
|
75
|
-
def type_for param
|
76
|
-
param_definitions[param][:type]
|
77
|
-
end
|
78
|
-
|
79
|
-
# All typed params with their descriptions
|
80
|
-
def typed_params
|
81
|
-
definitions_for(:type)
|
82
|
-
end
|
83
|
-
|
84
|
-
# List of params that have descriptions
|
85
|
-
def typed_param_names
|
86
|
-
params_with(:type)
|
87
|
-
end
|
88
|
-
|
89
|
-
require 'date'
|
90
|
-
|
91
111
|
# Coerce all params with types defined to their proper form
|
92
112
|
def resolve_types!
|
93
|
-
|
94
|
-
val
|
113
|
+
params_with(:type).each do |param, type|
|
114
|
+
val = self[param]
|
95
115
|
case
|
96
116
|
when val.nil? then val = nil
|
97
117
|
when (type == :boolean) then
|
98
118
|
if ['false', false, 0, '0', ''].include?(val) then val = false else val = true end
|
99
|
-
when (
|
100
|
-
val = val.split(",")
|
101
|
-
|
102
|
-
when (val.
|
119
|
+
when (type == Array)
|
120
|
+
if val.is_a?(String) then val = val.split(",") rescue nil ; end
|
121
|
+
# for all following types, map blank/empty to nil
|
122
|
+
when (val.respond_to?(:empty?) && val.empty?) then val = nil
|
103
123
|
when (type == :filename) then val = File.expand_path(val)
|
104
124
|
when (type == Float) then val = val.to_f
|
105
125
|
when (type == Integer) then val = val.to_i
|
106
126
|
when (type == Symbol) then val = val.to_s.to_sym rescue nil
|
127
|
+
when (type == Regexp) then val = Regexp.new(val) rescue nil
|
107
128
|
when ((val.to_s == 'now') && (type == Date)) then val = Date.today
|
108
129
|
when ((val.to_s == 'now') && (type == DateTime)) then val = DateTime.now
|
109
|
-
when (type ==
|
110
|
-
when
|
111
|
-
|
112
|
-
else # nothing
|
130
|
+
when ((val.to_s == 'now') && (type == Time)) then val = Time.now
|
131
|
+
when [Date, Time, DateTime].include?(type) then val = type.parse(val) rescue nil
|
132
|
+
else true # nothing
|
113
133
|
end
|
114
134
|
self[param] = val
|
115
135
|
end
|
@@ -124,41 +144,14 @@ module Configliere
|
|
124
144
|
# Settings.define :param, :required => true
|
125
145
|
#
|
126
146
|
|
127
|
-
# List of params that are required
|
128
|
-
# @return [Array] list of required params
|
129
|
-
def required_params
|
130
|
-
params_with(:required)
|
131
|
-
end
|
132
|
-
|
133
147
|
# Check that all required params are present.
|
134
148
|
def validate_requireds!
|
135
149
|
missing = []
|
136
|
-
|
137
|
-
missing << param if self[param].nil?
|
150
|
+
params_with(:required).each do |param, is_required|
|
151
|
+
missing << param if self[param].nil? && is_required
|
138
152
|
end
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
# all params with a value for the definable aspect
|
143
|
-
#
|
144
|
-
# @param definable the aspect to list (:description, :type, :encrypted, etc.)
|
145
|
-
def params_with defineable
|
146
|
-
param_definitions.keys.find_all{|param| param_definitions[param][defineable] } || []
|
147
|
-
end
|
148
|
-
|
149
|
-
# all params without a value for the definable aspect
|
150
|
-
#
|
151
|
-
# @param definable the aspect to reject (:description, :type, :encrypted, etc.)
|
152
|
-
def params_without defineable
|
153
|
-
param_definitions.keys.reject{|param| param_definitions[param].include?(defineable) } || []
|
154
|
-
end
|
155
|
-
|
156
|
-
def definitions_for defineable
|
157
|
-
hsh = {}
|
158
|
-
param_definitions.each do |param, defs|
|
159
|
-
hsh[param] = defs[defineable] if defs[defineable]
|
160
|
-
end
|
161
|
-
hsh
|
153
|
+
return if missing.empty?
|
154
|
+
raise "Missing values for: #{missing.map{|pn| d = definition_of(pn, :description) ; (d ? "#{pn} (#{d})" : pn.to_s) }.sort.join(", ")}"
|
162
155
|
end
|
163
156
|
|
164
157
|
# Pretend that any #define'd parameter is a method
|
@@ -170,7 +163,7 @@ module Configliere
|
|
170
163
|
def method_missing meth, *args
|
171
164
|
meth.to_s =~ /^(\w+)(=)?$/ or return super
|
172
165
|
name, setter = [$1.to_sym, $2]
|
173
|
-
return(super) unless
|
166
|
+
return(super) unless has_definition?(name)
|
174
167
|
if setter && (args.size == 1)
|
175
168
|
self[name] = args.first
|
176
169
|
elsif (!setter) && args.empty?
|
@@ -179,8 +172,9 @@ module Configliere
|
|
179
172
|
end
|
180
173
|
|
181
174
|
end
|
175
|
+
|
176
|
+
# Define is included by default
|
182
177
|
Param.class_eval do
|
183
178
|
include Configliere::Define
|
184
179
|
end
|
185
180
|
end
|
186
|
-
|
@@ -1,9 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'configliere/crypter'
|
3
2
|
module Configliere
|
4
3
|
module EncryptedParam
|
5
|
-
# The password used in encrypting params during serialization
|
6
|
-
attr_accessor :encrypt_pass
|
7
4
|
|
8
5
|
# decrypts any encrypted params
|
9
6
|
# then calls the next step in the resolve! chain.
|
@@ -17,7 +14,7 @@ module Configliere
|
|
17
14
|
def resolve_encrypted!
|
18
15
|
remove_and_adopt_encrypt_pass_param_if_any!
|
19
16
|
encrypted_params.each do |param|
|
20
|
-
encrypted_val = deep_delete(*
|
17
|
+
encrypted_val = deep_delete(*encrypted_key_path(param)) or next
|
21
18
|
self[param] = self.decrypted(encrypted_val)
|
22
19
|
end
|
23
20
|
end
|
@@ -27,52 +24,54 @@ module Configliere
|
|
27
24
|
# @example
|
28
25
|
# Settings.defaults :username=>"mysql_username", :password=>"mysql_password"
|
29
26
|
# Settings.define :password, :encrypted => true
|
30
|
-
# Settings.
|
27
|
+
# Settings.export
|
31
28
|
# #=> {:username => 'mysql_username', :password=>"\345?r`\222\021"\210\312\331\256\356\351\037\367\326" }
|
32
29
|
def export
|
30
|
+
remove_and_adopt_encrypt_pass_param_if_any!
|
33
31
|
hsh = super()
|
34
32
|
encrypted_params.each do |param|
|
35
33
|
val = hsh.deep_delete(*convert_key(param)) or next
|
36
|
-
hsh.deep_set( *(
|
34
|
+
hsh.deep_set( *(encrypted_key_path(param) | [encrypted(val)]) )
|
37
35
|
end
|
38
36
|
hsh
|
39
37
|
end
|
40
38
|
|
41
39
|
# if :encrypted_pass was set as a param, remove it from the hash and set it as an attribute
|
42
40
|
def remove_and_adopt_encrypt_pass_param_if_any!
|
43
|
-
@encrypt_pass
|
41
|
+
@encrypt_pass ||= self.delete(:encrypt_pass) if self[:encrypt_pass]
|
42
|
+
@encrypt_pass ||= ENV['ENCRYPT_PASS'] if ENV['ENCRYPT_PASS']
|
44
43
|
end
|
45
44
|
|
46
45
|
# the chain of symbol keys for a dotted path key,
|
47
46
|
# prefixing the last one with "encrypted_"
|
48
47
|
#
|
49
48
|
# @example
|
50
|
-
#
|
49
|
+
# encrypted_key_path('amazon.api.key')
|
51
50
|
# #=> [:amazon, :api, :encrypted_key]
|
52
|
-
def
|
53
|
-
encrypted_path = convert_key(param)
|
51
|
+
def encrypted_key_path param
|
52
|
+
encrypted_path = Array(convert_key(param))
|
54
53
|
encrypted_path[-1] = "encrypted_#{encrypted_path.last}".to_sym
|
55
54
|
encrypted_path
|
56
55
|
end
|
57
56
|
|
58
57
|
# list of all params to encrypt on serialization
|
59
58
|
def encrypted_params
|
60
|
-
params_with(:encrypted)
|
59
|
+
params_with(:encrypted).keys.select{|p| definition_of(p, :encrypted) }
|
61
60
|
end
|
62
61
|
|
63
62
|
def decrypted val
|
64
|
-
return val if val.
|
65
|
-
Configliere::Crypter.decrypt(val, encrypt_pass)
|
63
|
+
return val.to_s if val.to_s.empty?
|
64
|
+
Configliere::Crypter.decrypt(val, @encrypt_pass)
|
66
65
|
end
|
67
66
|
|
68
67
|
def encrypted val
|
69
68
|
return unless val
|
70
|
-
Configliere::Crypter.encrypt(val, encrypt_pass)
|
69
|
+
Configliere::Crypter.encrypt(val, @encrypt_pass)
|
71
70
|
end
|
72
71
|
end
|
73
72
|
|
74
|
-
|
75
|
-
|
73
|
+
Param.on_use(:encrypted) do
|
74
|
+
use :config_file, :define
|
75
|
+
extend EncryptedParam
|
76
76
|
end
|
77
77
|
end
|
78
|
-
|
data/lib/configliere/env_var.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
Configliere.use :define
|
3
1
|
module Configliere
|
4
2
|
#
|
5
3
|
# EnvVar -- load configuration from environment variables
|
@@ -18,19 +16,19 @@ module Configliere
|
|
18
16
|
end
|
19
17
|
end
|
20
18
|
end
|
21
|
-
|
19
|
+
|
22
20
|
protected
|
23
21
|
def adopt_env_var! param, env
|
24
22
|
env = env.to_s
|
25
|
-
|
23
|
+
definition_of(param)[:env_var] ||= env
|
26
24
|
val = ENV[env]
|
27
25
|
self[param] = val if val
|
28
26
|
end
|
29
27
|
end
|
30
28
|
|
31
|
-
Param.
|
32
|
-
|
33
|
-
|
29
|
+
Param.on_use(:env_var) do
|
30
|
+
use :commandline
|
31
|
+
extend Configliere::EnvVar
|
34
32
|
end
|
35
33
|
end
|
36
34
|
|
data/lib/configliere/param.rb
CHANGED
@@ -1,15 +1,24 @@
|
|
1
|
-
require 'configliere/core_ext/sash.rb'
|
2
1
|
module Configliere
|
3
|
-
|
4
|
-
|
2
|
+
#
|
3
|
+
# We want to be able to call super() on these methods in all included models,
|
4
|
+
# so we define them in this parent shim class.
|
5
|
+
#
|
6
|
+
class ParamParent < DeepHash
|
7
|
+
# default export method: dup of self
|
5
8
|
def export
|
6
|
-
|
9
|
+
dup.tap{|hsh| hsh.each{|k,v| hsh[k] = v.respond_to?(:export) ? v.export : v } }
|
7
10
|
end
|
11
|
+
|
8
12
|
# terminate resolution chain
|
13
|
+
# @return self
|
9
14
|
def resolve!
|
15
|
+
self
|
10
16
|
end
|
11
|
-
|
17
|
+
|
18
|
+
# terminate validation chain.
|
19
|
+
# @return self
|
12
20
|
def validate!
|
21
|
+
self
|
13
22
|
end
|
14
23
|
end
|
15
24
|
|
@@ -21,26 +30,6 @@ module Configliere
|
|
21
30
|
#
|
22
31
|
class Param < Configliere::ParamParent
|
23
32
|
|
24
|
-
# @param constructor<Object>
|
25
|
-
# The default value for the mash. Defaults to an empty hash.
|
26
|
-
#
|
27
|
-
# @details [Alternatives]
|
28
|
-
# If constructor is a Hash, a new mash will be created based on the keys of
|
29
|
-
# the hash and no default value will be set.
|
30
|
-
def initialize(constructor = {})
|
31
|
-
if constructor.is_a?(Hash)
|
32
|
-
super()
|
33
|
-
update(constructor) unless constructor.empty?
|
34
|
-
else
|
35
|
-
super(constructor)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# @return [Hash] The mash as a Hash with string keys.
|
40
|
-
def to_hash
|
41
|
-
Hash.new(default).merge(self)
|
42
|
-
end
|
43
|
-
|
44
33
|
#
|
45
34
|
# Incorporates the given settings.
|
46
35
|
# alias for deep_merge!
|
@@ -53,60 +42,44 @@ module Configliere
|
|
53
42
|
# Settings.defaults :basket => :tasket, :moon => { :cow => :smiling }
|
54
43
|
# Config #=> { :hat => :cat, :basket => :tasket, :moon => { :man => :smiling, :cow => :jumping } }
|
55
44
|
#
|
45
|
+
# @return self
|
56
46
|
def defaults hsh
|
57
47
|
deep_merge! hsh
|
48
|
+
self
|
58
49
|
end
|
59
50
|
|
60
|
-
# Finalize and validate params
|
51
|
+
# Finalize and validate params. All include'd modules and subclasses *must* call super()
|
52
|
+
# @return self
|
61
53
|
def resolve!
|
62
54
|
super()
|
63
55
|
validate!
|
56
|
+
self
|
64
57
|
end
|
65
|
-
|
58
|
+
|
59
|
+
# Check that all defined params are valid. All include'd modules and subclasses *must*call super()
|
60
|
+
# @return self
|
66
61
|
def validate!
|
67
62
|
super()
|
63
|
+
self
|
68
64
|
end
|
69
65
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
66
|
+
def use *mws
|
67
|
+
hsh = mws.pop if mws.last.is_a?(Hash)
|
68
|
+
Configliere.use(*mws)
|
69
|
+
mws.each do |mw|
|
70
|
+
if (blk = USE_HANDLERS[mw])
|
71
|
+
instance_eval(&blk)
|
72
|
+
end
|
75
73
|
end
|
74
|
+
self.deep_merge!(hsh) if hsh
|
75
|
+
self
|
76
76
|
end
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def delete param
|
87
|
-
if param =~ /\./
|
88
|
-
return deep_delete( *convert_key(param) )
|
89
|
-
else
|
90
|
-
super param
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def use *args
|
95
|
-
hsh = args.pop if args.last.is_a?(Hash)
|
96
|
-
Configliere.use(*args)
|
97
|
-
self.deep_merge!(hsh) unless hsh.nil?
|
98
|
-
end
|
99
|
-
|
100
|
-
protected
|
101
|
-
# @param key<Object> The key to convert.
|
102
|
-
#
|
103
|
-
# @param [Object]
|
104
|
-
# The converted key. A dotted param ('moon.cheese.type') becomes
|
105
|
-
# an array of sequential keys for deep_set and deep_get
|
106
|
-
#
|
107
|
-
# @api private
|
108
|
-
def convert_key dotted
|
109
|
-
dotted.to_s.split(".").map{|key| key.to_sym }
|
78
|
+
# @private
|
79
|
+
USE_HANDLERS = {} unless defined?(USE_HANDLERS)
|
80
|
+
# Block executed when use is invoked
|
81
|
+
def self.on_use mw, &block
|
82
|
+
USE_HANDLERS[mw] = block
|
110
83
|
end
|
111
84
|
|
112
85
|
end
|