module Aquarium::Utils::OptionsUtils
OptionsUtils
¶ ↑
Support parsing and processing of key-value pairs of options, where the values are always converted to Sets. Types including this module should have their initialize
methods call this module's init_specification
to do the options processing. See its documentation for more details.
Several class methods are included for defining convenience instance methods. For example, for options :foo
and :bar
, calling:
canonical_options_given_methods :foo, :bar
will define several methods for each option specified, e.g.,:
foo_given # => returns the value of @specification[:foo] foo_given? # => returns true "foo_given" is not nil or empty. bar_given # etc... bar_given?
If you would like corresponding reader and writer methods, pass a list of the keys for which you want these methods defined to one of the following methods:
canonical_option_reader :foo, :bar # analogous to attr_reader canonical_option_writer :foo, :bar # analogous to attr_writer canonical_option_accessor :foo, :bar # analogous to attr_accessor
For all of these methods, you can also pass CANONICAL_OPTIONS
(discussed below) to define methods for all of the “canonical” options, e.g.,
canonical_option_accessor CANONICAL_OPTIONS
These methods are not defined by default to prevent accidentally overriding other methods that you might have defined with the same names. Also, note that the writer methods will convert the inputs to sets, following the conventions for the options and the readers will return the sets. If you want different handling, you'll have to provide custom implementations.
Note that special-case accessor methods are already defined for the :noop
and :logger
options (discussed below) where the writers expect single values, not sets, and the readers return the single values. (Yea, it's a bit inconsistent…)
Finally, these canonical_option_*
methods should only be called with the keys for the CANONICAL_OPTIONS
. The keys are considered the “canonical options”, while the values for the keys are synonyms that can be used instead.
This module also defines several universal options that will be available to all types that include this module:
:logger
-
A Ruby standard library Logger used for any messages. A default system-wide logger is used otherwise. The corresponding
logger
andlogger=
accessors are defined. :logger_stream
-
An an alternative to defining the logger, you can define just the output stream where log output will be written. If this option is specified, a new logger will be created for the instance with this output stream. There are no corresponding accessors; use the appropriate methods on the
logger
object instead. :severity
-
The logging severity level, one of the Logger::Severity values or a corresponding integer value. If this option is specified, a new logger will be created for the instance with this output stream. There are no corresponding accessors; use the corresponding methods on the
logger
object instead. :noop => options_hash[:noop] || false
-
If true, don't do “anything”, the interpretation of which will vary with the type receiving the option. For example, a type might go through some initialization, such as parsng its options, but do nothing after that. Primarily useful for debugging and testing.
The value can be accessed through the
noop
andnoop=
accessors.
Attributes
Public Class Methods
# File lib/aquarium/utils/options_utils.rb 227 def self.append_features clazz 228 super 229 ClassMethods.send :append_features, (class << clazz; self; end) 230 end
# File lib/aquarium/utils/options_utils.rb 74 def self.universal_options 75 [:logger_stream, :logger, :severity, :noop] 76 end
# File lib/aquarium/utils/options_utils.rb 78 def self.universal_prepositions 79 [:for, :on, :in, :within] 80 end
Public Instance Methods
# File lib/aquarium/utils/options_utils.rb 125 def hashify options 126 return options if options.kind_of?(Hash) 127 new_options = {} 128 options = [options] unless options.kind_of?(Array) 129 options.each do |x| 130 if x.kind_of?(Hash) 131 new_options.merge!(x) 132 else 133 new_options[x] = Set.new([]) 134 end 135 end 136 new_options 137 end
Class initialize methods call this method to process the input options. Pass an optional block to the method that takes no parameters if you want to do additional processing of the options before init_specification
validates the options. The block will have access to the @specification hash built up by init_specification
and to a new attribute @original_options, which will be a copy of the original options passed to init_specification
(it will be either a hash or an array). Finally, if the block returns a value or an array of values, they will be treated as keys to ignore in the options when they are validated. This is a way of dynamically treating an option as valid that can't be known in advance. (See Aspect and Pointcut for examples of this feature in use.)
# File lib/aquarium/utils/options_utils.rb 95 def init_specification options, canonical_options, additional_allowed_options = [] 96 @canonical_options = canonical_options 97 @additional_allowed_options = additional_allowed_options.map{|x| x.respond_to?(:intern) ? x.intern : x} 98 @original_options = options.nil? ? {} : options.dup 99 @specification = {} 100 options ||= {} 101 options_hash = hashify options 102 @canonical_options.keys.each do |key| 103 all_related_options = make_array(options_hash[key.intern]) || [] 104 @canonical_options[key].inject(all_related_options) do |ary, o| 105 ary << options_hash[o.intern] if options_hash[o.intern] 106 ary 107 end 108 @specification[key.intern] = Set.new(all_related_options.flatten) 109 end 110 111 OptionsUtils::universal_options.each do |uopt| 112 @specification[uopt] = Set.new(make_array(options_hash[uopt])) unless options_hash[uopt].nil? 113 end 114 @specification[:noop] ||= Set.new([false]) 115 set_logger_if_stream_specified 116 set_logger_severity_if_specified 117 set_default_logger_if_not_specified 118 119 ignorables = yield if block_given? 120 ignorables = [] if ignorables.nil? 121 ignorables = [ignorables] unless ignorables.kind_of? Array 122 validate_options(options_hash.reject {|k,v| ignorables.include?(k)}) 123 end
# File lib/aquarium/utils/options_utils.rb 139 def validate_options options 140 unknowns = options.keys - all_allowed_option_symbols - OptionsUtils::universal_options 141 raise Aquarium::Utils::InvalidOptions.new("Unknown options specified: #{unknowns.inspect}") if unknowns.size > 0 142 end