summaryrefslogtreecommitdiff
path: root/lib/chef/node/attribute_trait/decorator.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/node/attribute_trait/decorator.rb')
-rw-r--r--lib/chef/node/attribute_trait/decorator.rb124
1 files changed, 84 insertions, 40 deletions
diff --git a/lib/chef/node/attribute_trait/decorator.rb b/lib/chef/node/attribute_trait/decorator.rb
index 6effd389d8..59d71febfa 100644
--- a/lib/chef/node/attribute_trait/decorator.rb
+++ b/lib/chef/node/attribute_trait/decorator.rb
@@ -5,12 +5,11 @@ class Chef
attr_accessor :wrapped_object
#
- # Delegate methods common to Array and Hash
- # - this is done for speed over method_missing
- # - some of these methods are overridden later with different semantics
+ # Performance Delegation
#
+
methods = ( Array.instance_methods & Hash.instance_methods ) - Object.instance_methods +
- [ :!, :!=, :<=>, :==, :===, :eql?, :to_s, :hash ]
+ [ :!, :!=, :<=>, :==, :===, :eql?, :to_s, :hash, :key, :has_key? ]
methods.each do |method|
define_method method do |*args, &block|
@@ -18,6 +17,10 @@ class Chef
end
end
+ #
+ # Construction
+ #
+
def self.included(base)
base.extend(ClassMethods)
end
@@ -32,6 +35,14 @@ class Chef
@wrapped_object = wrapped_object
end
+ def new_decorator(**args)
+ self.class.new(**args)
+ end
+
+ #
+ # Conversion
+ #
+
def ffi_yajl(*opts)
for_json.ffi_yajl(*opts)
end
@@ -50,6 +61,10 @@ class Chef
end
end
+ #
+ # Inspection
+ #
+
def is_a?(klass)
wrapped_object.is_a?(klass) || super
end
@@ -58,6 +73,10 @@ class Chef
wrapped_object.kind_of?(klass) || super
end
+ #
+ # Extended API
+ #
+
def regular_writer(*path, value)
last_key = path.pop
obj = path.inject(wrapped_object) { |memo, key| memo[key] }
@@ -85,25 +104,13 @@ class Chef
hash.delete(last)
end
- def [](key)
- maybe_decorated_value(wrapped_object[key])
- end
-
- def maybe_decorated_value(val)
- if val.is_a?(Hash) || val.is_a?(Array)
- new_decorator(wrapped_object: val)
- else
- val
- end
- end
-
- def new_decorator(**args)
- self.class.new(**args)
- end
+ #
+ # method_missing
+ #
def method_missing(method, *args, &block)
if wrapped_object.respond_to?(method, false)
- # cannot define_method here
+ # do not define_method here
wrapped_object.public_send(method, *args, &block)
else
super
@@ -122,34 +129,41 @@ class Chef
wrapped_object.respond_to?(method, false) || super
end
+ #
+ # Decorated Methods
+ #
- def initialize_copy(source)
- super
- @wrapped_object = safe_dup(source.wrapped_object)
- end
-
- def include?(key)
- wrapped_object.include?(key)
- end
-
- # performance
- def key?(key)
- wrapped_object.key?(key)
+ def [](key)
+ maybe_decorated_value(wrapped_object[key])
end
- # performance
- def has_key?(key)
- wrapped_object.has_key?(key)
+ def any?(&block)
+ block ||= ->(o) { o }
+ if is_a?(Hash)
+ each do |key, value|
+ if yield key, value
+ return true
+ end
+ end
+ elsif is_a?(Array)
+ each do |key|
+ if yield key
+ return true
+ end
+ end
+ else
+ return wrapped_object.any?(&block)
+ end
+ false
end
- # we need to be careful to return decorated values when appropriate
def each(&block)
return enum_for(:each) unless block_given?
- if wrapped_object.is_a?(Array)
+ if is_a?(Array)
wrapped_object.each_with_index do |value, i|
yield self[i]
end
- elsif wrapped_object.is_a?(Hash)
+ elsif is_a?(Hash)
if block.arity > 1
wrapped_object.each do |key, value|
yield key, self[key]
@@ -160,14 +174,29 @@ class Chef
end
end
else
- # dunno...
wrapped_object.each(&block)
end
end
- # return decorated values when appropriate
alias_method :each_pair, :each
+ def map(&block)
+ return enum_for(:map) unless block_given?
+ if is_a?(Array)
+ ret = []
+ each do |elem|
+ ret.push(yield elem)
+ end
+ ret
+ else
+ wrapped_object.map(&block)
+ end
+ end
+
+ #
+ # Copying and dup'ing
+ #
+
# nil, true, false and Fixnums are not dup'able
def safe_dup(e)
e.dup
@@ -187,6 +216,21 @@ class Chef
end
end
+ def initialize_copy(source)
+ super
+ @wrapped_object = safe_dup(source.wrapped_object)
+ end
+
+ private
+
+ def maybe_decorated_value(val)
+ if val.is_a?(Hash) || val.is_a?(Array)
+ new_decorator(wrapped_object: val)
+ else
+ val
+ end
+ end
+
end
end
end