Class: NsOptions::Namespace
- Inherits:
-
Object
- Object
- NsOptions::Namespace
- Defined in:
- lib/ns-options/namespace.rb
Instance Attribute Summary collapse
-
#metaclass ⇒ Object
Returns the value of attribute metaclass.
-
#options ⇒ Object
Returns the value of attribute options.
Instance Method Summary collapse
-
#apply(option_values = {}) ⇒ Object
The opposite of #to_hash.
-
#define(&block) ⇒ Object
The define method is provided for convenience and commonization.
-
#each ⇒ Object
allow for iterating over the key/values of a namespace this uses #to_hash so you won’t get option/namespace objs for the values.
-
#initialize(key, parent = nil, &block) ⇒ Namespace
constructor
Every namespace tracks a metaclass to allow for individual reader/writers for their options, without any collisions.
- #inspect(*args) ⇒ Object
-
#method_missing(method, *args, &block) ⇒ Object
There are a number of cases we want to watch for: 1.
-
#namespace(name, key = nil, &block) ⇒ Object
(also: #ns)
Define a namespace under this namespace.
-
#option(*args) ⇒ Object
(also: #opt)
Define an option for this namespace.
-
#required_set? ⇒ Boolean
(also: #valid?)
This is a helper to check if options that were defined as :required have been set.
- #respond_to?(method) ⇒ Boolean
-
#to_hash ⇒ Object
return a hash representation of the namespace use symbols for the hash.
Constructor Details
#initialize(key, parent = nil, &block) ⇒ Namespace
Every namespace tracks a metaclass to allow for individual reader/writers for their options, without any collisions. Since every namespace is of the same class, defining option reader and writer methods directly on the class would make multiple namespaces with different options impossible.
10 11 12 13 14 |
# File 'lib/ns-options/namespace.rb', line 10 def initialize(key, parent = nil, &block) self. = (class << self; self; end) self. = NsOptions::Options.new(key, parent) self.define(&block) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
There are a number of cases we want to watch for:
-
A reader of a ‘known’ option. This case is for an option that’s been defined for an ancestor of this namespace but not directly for this namespace. In this case we fetch the options definition and use it to define the option directly for this namespace.
-
TODO
-
A writer of a ‘known’ option. This case is similar to the above, but instead we are wanting to write a value. We need to fetch the option definition, define it and then we write the option as we normally would.
-
A dynamic writer. The option is not ‘known’ to the namespace, so we use the value and it’s class to define the option for this namespace. Then we just use the writer as we normally would.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/ns-options/namespace.rb', line 130 def method_missing(method, *args, &block) option_name = method.to_s.gsub("=", "") value = args.size == 1 ? args[0] : args if args.empty? && self.respond_to?(option_name) option = NsOptions::Helper.find_and_define_option(self, option_name) self.send(option.name) elsif args.empty? && (namespace = self..get_namespace(option_name)) NsOptions::Helper.find_and_define_namespace(self, option_name) self.send(option_name) elsif !args.empty? && self.respond_to?(option_name) option = NsOptions::Helper.find_and_define_option(self, option_name) self.send("#{option.name}=", value) elsif !args.empty? option = self.option(option_name) self.send("#{option.name}=", value) else super end end |
Instance Attribute Details
#metaclass ⇒ Object
Returns the value of attribute metaclass.
4 5 6 |
# File 'lib/ns-options/namespace.rb', line 4 def @metaclass end |
#options ⇒ Object
Returns the value of attribute options.
4 5 6 |
# File 'lib/ns-options/namespace.rb', line 4 def @options end |
Instance Method Details
#apply(option_values = {}) ⇒ Object
The opposite of #to_hash. Takes a hash representation of options and namespaces and mass assigns option values.
68 69 70 71 72 73 74 75 76 77 |
# File 'lib/ns-options/namespace.rb', line 68 def apply(option_values = {}) option_values.each do |name, value| namespace = self..namespaces[name] if self.[name] || !namespace self.send("#{name}=", value) elsif namespace && value.kind_of?(Hash) namespace.apply(value) end end end |
#define(&block) ⇒ Object
The define method is provided for convenience and commonization. The internal system uses it to commonly use a block with a namespace. The method can be used externally when a namespace is created separately from where options are added/set on it. For example:
parent_namespace.namespace(:specific)
parent_namespace.specific.define do
option :root
end
Will define a new namespace under the parent namespace and then will later on add options to it.
110 111 112 113 114 115 116 117 |
# File 'lib/ns-options/namespace.rb', line 110 def define(&block) if block && block.arity > 0 yield self elsif block self.instance_eval(&block) end self end |
#each ⇒ Object
allow for iterating over the key/values of a namespace this uses #to_hash so you won’t get option/namespace objs for the values
94 95 96 |
# File 'lib/ns-options/namespace.rb', line 94 def each self.to_hash.each { |k,v| yield k,v if block_given? } end |
#inspect(*args) ⇒ Object
154 155 156 |
# File 'lib/ns-options/namespace.rb', line 154 def inspect(*args) "#<#{self.class}:#{'0x%x' % (self.object_id << 1)}:#{self..key} #{self.to_hash.inspect}>" end |
#namespace(name, key = nil, &block) ⇒ Object Also known as: ns
Define a namespace under this namespace. Firstly, a new key is constructured from this current namespace’s key and the name for the new namespace. The namespace is then added to the options collection. Finally a reader method is defined for accessing the namespace. With the following:
parent_namespace.namespace(:specific) do
option :root
end
you will get a reader for the namespace:
parent_namespace.specific # => returns the namespace parent_namespace.specific.root = “something” # => options are accessed in the same way
The defined namespaces is returned as well.
57 58 59 60 61 62 63 |
# File 'lib/ns-options/namespace.rb', line 57 def namespace(name, key = nil, &block) key = "#{self..key}:#{(key || name)}" NsOptions::Helper.advisor(self).is_this_sub_namespace_ok?(name, caller) namespace = self..add_namespace(name, key, self, &block) NsOptions::Helper.define_namespace_methods(self, name) namespace end |
#option(*args) ⇒ Object Also known as: opt
Define an option for this namespace. Add the option to the namespace’s options collection and then define accessors for the option. With the following:
namespace.option(:root, String, { :some_option => true })
you will get accessors for root:
namespace.root = “something” # set’s the root option to ‘something’ namespace.root # => “something” namespace.root(“something else”) # set’s the root option to ‘something-else`
The defined option is returned as well.
34 35 36 37 38 39 |
# File 'lib/ns-options/namespace.rb', line 34 def option(*args) NsOptions::Helper.advisor(self).is_this_option_ok?(args[0], caller) option = self..add(*args) NsOptions::Helper.define_option_methods(self, option) option end |
#required_set? ⇒ Boolean Also known as: valid?
This is a helper to check if options that were defined as :required have been set.
17 18 19 |
# File 'lib/ns-options/namespace.rb', line 17 def required_set? self..required_set? end |
#respond_to?(method) ⇒ Boolean
150 151 152 |
# File 'lib/ns-options/namespace.rb', line 150 def respond_to?(method) super || self..is_defined?(method.to_s.gsub("=", "")) end |
#to_hash ⇒ Object
return a hash representation of the namespace use symbols for the hash
81 82 83 84 85 86 87 88 89 90 |
# File 'lib/ns-options/namespace.rb', line 81 def to_hash Hash.new.tap do |out| self..each do |name, opt| out[name.to_sym] = opt.value end self..namespaces.each do |name, value| out[name.to_sym] = value.to_hash end end end |