module Poise::Helpers::Subresources::Child
A resource mixin for child subresources.
@since 1.0.0
Public Instance Methods
after_created()
click to toggle source
Register ourself with parents in case this is not a nested resource.
@api private
Calls superclass method
# File lib/poise/helpers/subresources/child.rb, line 74 def after_created super self.class.parent_attributes.each_key do |name| parent = self.send(name) parent.register_subresource(self) if parent && parent.respond_to?(:register_subresource) end end
parent(*args)
click to toggle source
@overload parent()
Get the parent resource for this child. This may be nil if the resource is set to parent_optional = true. @return [Chef::Resource, nil]
@overload parent(val)
Set the parent resource. The parent can be set as resource object, a string (either a bare resource name or a type[name] string), or a type:name hash. @param val [String, Hash, Chef::Resource] Parent resource to set. @return [Chef::Resource, nil]
# File lib/poise/helpers/subresources/child.rb, line 63 def parent(*args) # Lie about this method if the parent type is true. if self.class.parent_type == true raise NoMethodError.new("undefined method `parent' for #{self}") end _parent(:parent, self.class.parent_type, self.class.parent_optional, self.class.parent_auto, self.class.parent_default, *args) end
Private Instance Methods
_parent(name, parent_type, parent_optional, parent_auto, parent_default, *args)
click to toggle source
Generic form of the parent getter/setter.
@since 2.0.0 @see parent
# File lib/poise/helpers/subresources/child.rb, line 88 def _parent(name, parent_type, parent_optional, parent_auto, parent_default, *args) # Allow using a DSL symbol as the parent type. if parent_type.is_a?(Symbol) parent_type = Chef::Resource.resource_for_node(parent_type, node) end # Grab the ivar for local use. parent_ref = instance_variable_get(:"@#{name}") if !args.empty? val = args.first if val.nil? # Unsetting the parent. parent = parent_ref = nil else if val.is_a?(String) && !val.include?('[') raise Poise::Error.new("Cannot use a string #{name} without defining a parent type") if parent_type == Chef::Resource # Try to find the most recent instance of parent_type with a # matching name. This takes subclassing parent_type into account. found_val = nil iterator = run_context.resource_collection.respond_to?(:recursive_each) ? :recursive_each : :each # This will find the last matching value due to overwriting # found_val as it goes. Will be the nearest match. run_context.resource_collection.public_send(iterator) do |res| found_val = res if res.is_a?(parent_type) && res.name == val end # If found_val is nil, fall back to using lookup even though # it won't work with subclassing, better than nothing? val = found_val || "#{parent_type.resource_name}[#{val}]" end if val.is_a?(String) || val.is_a?(Hash) parent = @run_context.resource_collection.find(val) else parent = val end if !parent.is_a?(parent_type) raise Poise::Error.new("Parent resource is not an instance of #{parent_type.name}: #{val.inspect}") end parent_ref = ParentRef.new(parent) end elsif !parent_ref || !parent_ref.resource if parent_default parent = if parent_default.is_a?(Chef::DelayedEvaluator) instance_eval(&parent_default) else parent_default end end # The @parent_ref means we won't run this if we previously set # ParentRef.new(nil). This means auto-lookup only happens during # after_created. if !parent && !parent_ref && parent_auto # Automatic sibling lookup for sequential composition. # Find the last instance of the parent class as the default parent. # This is super flaky and should only be a last resort. parent = Poise::Helpers::Subresources::DefaultContainers.find(parent_type, run_context, self_resource: self) end # Can't find a valid parent, if it wasn't optional raise an error. raise Poise::Error.new("No #{name} found for #{self}") unless parent || parent_optional parent_ref = ParentRef.new(parent) else parent = parent_ref.resource end raise Poise::Error.new("Cannot set the #{name} of #{self} to itself") if parent.equal?(self) # Store the ivar back. instance_variable_set(:"@#{name}", parent_ref) # Return the actual resource. parent end