Module: UsingYAML
- Defined in:
- lib/using_yaml.rb,
lib/using_yaml/hash.rb,
lib/using_yaml/array.rb,
lib/using_yaml/nilclass.rb
Overview
UsingYAML provides convenient class extensions which make it easy to interact with YAML-storage of settings files by defining accessors which allow one to talk to the files as if they were fully implemented classes.
Each of these files will be automagically enhanced to provide save and clean methods of talking to your YAML files without needing to worry about checking for nil’s, re-serializing or long-winded hash access.
This module also provides some static access to make it easy to enable/disable options such as squelching error messages (in production) and tracking where instances should load their files from.
See using_yaml
for usage information.
Defined Under Namespace
Modules: ClassMethods, InstanceMethods
Constant Summary collapse
- NilClass =
add_nilclass_extensions(nil, nil)
Class Method Summary collapse
-
.add_array_extensions(array, pathname) ⇒ Object
Calls add_extensions on all children.
-
.add_extensions(object, pathname = nil) ⇒ Object
Extends the incoming Array/Hash with magic which makes it possible to
save
and (in the case of Hashes) use methods instead of []-access. -
.add_hash_extensions(hash, pathname) ⇒ Object
Calls add_extensions on all children.
- .add_nilclass_extensions(instance, pathname) ⇒ Object
- .included(base) ⇒ Object
-
.path(klass) ⇒ Object
Returns the path where the given class will load from.
-
.path=(args) ⇒ Object
Sets the the path where the given class will load from.
-
.squelch! ⇒ Object
Because of the “safety” UsingYAML provides, it is easy for typos to creep in, which might result in unexpected nil’s.
-
.squelched? ⇒ Boolean
Returns true if UsingYAML will warn about potential typos (or similar) which might otherwise be masked.
-
.unsquelch! ⇒ Object
Opposite of
squelch!
.
Class Method Details
.add_array_extensions(array, pathname) ⇒ Object
Calls add_extensions on all children. Also defines a save
method iff this is a top-level UsingYAML object (see below for details).
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/using_yaml/array.rb', line 4 def self.add_array_extensions(array, pathname) # Here we define a Module to extend the array extensions = Module.new do # Iterate over the items array.each do |item| # Recursively continue to extend. UsingYAML.add_extensions(item) end # Define a save method if a pathname was supplied (only happens # on the top-level object - that is, example.foo will have a # +save+, but example.foo.bar will not). if pathname define_method(:save) do # Serialise using +to_yaml+ File.open(pathname, 'w') do |f| f.puts self.to_yaml end end end end # Load in the extensions for this instance array.extend(extensions) array end |
.add_extensions(object, pathname = nil) ⇒ Object
Extends the incoming Array/Hash with magic which makes it possible to save
and (in the case of Hashes) use methods instead of []-access.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/using_yaml.rb', line 31 def add_extensions(object, pathname = nil) case object when Array add_array_extensions(object, pathname) when Hash add_hash_extensions(object, pathname) when ::NilClass if pathname add_nilclass_extensions(object, pathname) else UsingYAML::NilClass end end object end |
.add_hash_extensions(hash, pathname) ⇒ Object
Calls add_extensions on all children. Also defines a save
method iff this is a top-level UsingYAML object (see below for details).
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/using_yaml/hash.rb', line 4 def self.add_hash_extensions(hash, pathname) # Here we define a Module to extend the hash extensions = Module.new do # Recursively continue to extend. hash.each_pair do |key, value| UsingYAML.add_extensions(value) end define_method(:method_missing) do |*args| name = args.shift.to_s if args.empty? value = send(:[], name) value.nil? ? UsingYAML::NilClass : value elsif args.size == 1 && name =~ /(.+)=/ # This is an "alias" turning self.key= into self[key]= # Also extends the incoming value so that it behaves # consistently with the other key-value pairs. key = $1 value = args.first # Save the value in the hashtable send(:[]=, key, UsingYAML.add_extensions(value)) # Define the new reader (as above) new_reader_extension = Module.new do define_method(key) do send(:[], key) || UsingYAML.add_extensions(nil) end end extend(new_reader_extension) value else super(name, args) end end # Define a save method if a pathname was supplied (only happens # on the top-level object - that is, example.foo will have a # +save+, but example.foo.bar will not). if pathname define_method(:save) do # Serialise using +to_yaml+ File.open(pathname, 'w') do |f| f.puts self.to_yaml end end end end # Load in the extensions for this instance hash.extend(extensions) hash end |
.add_nilclass_extensions(instance, pathname) ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/using_yaml/nilclass.rb', line 2 def self.add_nilclass_extensions(instance, pathname) extensions = Module.new do define_method(:method_missing) do |*args| # Child objects should not have #save if respond_to? :save UsingYAML::NilClass else # One nil is the same as the next :) self end end # Define a save method if a pathname was supplied (only happens # on the top-level object - that is, example.foo will have a # +save+, but example.foo.bar will not). if pathname # Being nil translates to "no file", not to "empty file", so we # want to actually delete any existing file. This is a semantic # difference, but important: there is a huge different between # an _empty_ file and a _non-existant_ file. YAML does not # reflect this difference, so we do. define_method(:save) do # If we can't delete it (permissions, ENOENT..), then there # ain't much we can do, so just squelch the error. FileUtils.rm(pathname) rescue nil end end end instance.extend(extensions) instance end |
.included(base) ⇒ Object
84 85 86 |
# File 'lib/using_yaml.rb', line 84 def self.included(base) base.extend UsingYAML::ClassMethods end |
.path(klass) ⇒ Object
Returns the path where the given class will load from. See using_yaml_path
for information on how to override this on a per-instance basis.
51 52 53 |
# File 'lib/using_yaml.rb', line 51 def path(klass) return @@path[klass] if defined?(@@path) end |
.path=(args) ⇒ Object
Sets the the path where the given class will load from. See using_yaml_path
for information on how to override this on a per-instance basis.
58 59 60 |
# File 'lib/using_yaml.rb', line 58 def path=(args) (@@path ||= {})[args.first] = args.last end |
.squelch! ⇒ Object
Because of the “safety” UsingYAML provides, it is easy for typos to creep in, which might result in unexpected nil’s. UsingYAML therefore is verbose in warning about these potential errors.
This method disables those warnings, which is useful in a production environment or if you are sure you aren’t making mistakes.
68 69 70 |
# File 'lib/using_yaml.rb', line 68 def squelch! @@squelched = true end |
.squelched? ⇒ Boolean
Returns true if UsingYAML will warn about potential typos (or similar) which might otherwise be masked.
74 75 76 |
# File 'lib/using_yaml.rb', line 74 def squelched? defined?(@@squelched) && @@squelched end |
.unsquelch! ⇒ Object
Opposite of squelch!
79 80 81 |
# File 'lib/using_yaml.rb', line 79 def unsquelch! @@squelched = false end |