Module: Configurable::Utils
- Defined in:
- lib/configurable/utils.rb
Overview
Utility methods to dump and load configurations, particularly nested configurations.
Constant Summary collapse
- DEFAULT_DUMP =
A block performing the default YAML dump.
default_dump_block- DEFAULT_LOAD =
A block performing the default load.
default_load_block
Class Method Summary collapse
-
.dump(delegates, target = "") ⇒ Object
Dumps delegates to target as yaml.
-
.dump_file(delegates, path, recurse = false, preview = false, &block) ⇒ Object
Dumps the delegates to the specified file.
-
.load(str) ⇒ Object
Loads the string as YAML.
-
.load_file(path, recurse = false, &block) ⇒ Object
Loads the file contents as YAML.
-
.recursive_path(key, path) ⇒ Object
A helper to create and prepare a recursive dump path.
Class Method Details
.dump(delegates, target = "") ⇒ Object
Dumps delegates to target as yaml. Delegates are output in order, and symbol keys are be stringified if delegates has been extended with IndifferentAccess (this produces a nicer config file).
class DumpExample
include Configurable
config :sym, :value # a symbol config
config 'str', 'value' # a string config
end
Utils.dump(DumpExample.configurations, "\n")
# => %q{
# sym: :value
# str: value
# }
Dump may be provided with a block to format each (key, delegate) pair; the block results are pushed directly to target, so newlines must be specified manually.
Utils.dump(DumpExample.configurations, "\n") do |key, delegate|
yaml = YAML.dump({key => delegate.default})[5..-1]
"# #{delegate[:desc]}\n#{yaml}\n"
end
# => %q{
# # a symbol config
# sym: :value
#
# # a string config
# str: value
#
# }
60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/configurable/utils.rb', line 60 def dump(delegates, target="") return dump(delegates, target, &DEFAULT_DUMP) unless block_given? stringify = delegates.kind_of?(IndifferentAccess) delegates.each_pair do |key, delegate| key = key.to_s if stringify && key.kind_of?(Symbol) target << yield(key, delegate) end target end |
.dump_file(delegates, path, recurse = false, preview = false, &block) ⇒ Object
Dumps the delegates to the specified file. If recurse is true, nested configurations are each dumped to their own file, based on the nesting key. For instance if you nested a in b:
a_configs = {
'key' => Delegate.new(:r, :w, 'a default')}
b_configs = {
'key' => Delegate.new(:r, :w, 'b default')}
'a' => Delegate.new(:r, :w, DelegateHash.new(a_configs))}}
Utils.dump_file(b_configs, 'b.yml')
File.read('b.yml') # => "key: b default"
File.read('b/a.yml') # => "key: a default"
In this way, each nested config gets it’s own file. The load_file method can recursively load configurations from this file structure. When recurse is false, all configs are dumped to a single file.
dump_file uses a method that collects all dumps in a preview array before dumping, so that the dump results can be redirected other places than the file system. If preview is set to false, no files will be created. The preview dumps are always returned by dump_file.
Note
For load_file to correctly load a recursive dump, all delegate hashes must use String keys. Symbol keys are allowed if the delegate hashes use IndifferentAccess; all other keys will not load properly. By default Configurable is set up to satisfy these conditions.
1.8 Bug: Currently dump_file with recurse=false will cause order to be lost in nested configs. See bahuvrihi.lighthouseapp.com/projects/21202-configurable/tickets/8
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/configurable/utils.rb', line 103 def dump_file(delegates, path, recurse=false, preview=false, &block) return dump_file(delegates, path, recurse, preview, &DEFAULT_DUMP) unless block_given? current = "" dumps = [[path, current]] dump(delegates, current) do |key, delegate| if recurse && delegate.is_nest? nested_delegates = delegate.default(false).delegates nested_dumps = dump_file(nested_delegates, recursive_path(key, path), true, true, &block) dumps.concat(nested_dumps) "" else yield(key, delegate) end end dumps.each do |dump_path, content| dir = File.dirname(dump_path) Dir.mkdir(dir) unless File.exists?(dir) File.open(dump_path, "w") do |io| io << content end end unless preview dumps end |
.load(str) ⇒ Object
Loads the string as YAML.
133 134 135 |
# File 'lib/configurable/utils.rb', line 133 def load(str) YAML.load(str) end |
.load_file(path, recurse = false, &block) ⇒ Object
Loads the file contents as YAML. If recurse is true, a hash will be recursively loaded. A block may be provided to set recursively loaded values in the hash loaded from the path.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/configurable/utils.rb', line 140 def load_file(path, recurse=false, &block) return load_file(path, recurse, &DEFAULT_LOAD) if recurse && !block_given? base = File.file?(path) ? (YAML.load_file(path) || {}) : {} if recurse # determine the files/dirs to load recursively # and add them to paths by key (ie the base # name of the path, minus any extname) paths = {} files, dirs = Dir.glob("#{path.chomp(File.extname(path))}/*").partition do |sub_path| File.file?(sub_path) end # directories are added to paths first so they can be # overridden by the files (appropriate since the file # will recursively load the directory if it exists) dirs.each do |dir| paths[File.basename(dir)] = dir end # when adding files, check that no two files map to # the same key (ex a.yml, a.yaml). files.each do |filepath| key = File.basename(filepath).chomp(File.extname(filepath)) if existing = paths[key] if File.file?(existing) confict = [File.basename(paths[key]), File.basename(filepath)].sort raise "multiple files load the same key: #{confict.inspect}" end end paths[key] = filepath end # recursively load each file and reverse merge # the result into the base paths.each_pair do |key, recursive_path| value = load_file(recursive_path, true, &block) yield(base, key, value) end end base end |
.recursive_path(key, path) ⇒ Object
A helper to create and prepare a recursive dump path.
186 187 188 189 190 191 |
# File 'lib/configurable/utils.rb', line 186 def recursive_path(key, path) ext = File.extname(path) dir = path.chomp(ext) "#{File.join(dir, key.to_s)}#{ext}" end |