configliere 0.3.4 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|