Module: Poise::Helpers::OptionCollector

Included in:
TemplateContent, Resource
Defined in:
lib/poise/helpers/option_collector.rb

Overview

A resource mixin to add a new kind of attribute, an option collector. These attributes can act as mini-DSLs for things which would otherwise be key/value pairs.

Examples:

Defining an option collector

class MyResource < Chef::Resource
  include Poise::Helpers::OptionCollector
  attribute(:my_options, option_collector: true)
end

Using an option collector

my_resource 'name' do
  my_options do
    key1 'value1'
    key2 'value2'
  end
end

Since:

  • 1.0.0

Class Method Summary collapse

Class Method Details

.attribute(name, options = {}) ⇒ Object

Override the normal #attribute() method to support defining option collectors too.

Since:

  • 1.0.0



70
71
72
73
74
75
76
77
78
# File 'lib/poise/helpers/option_collector.rb', line 70

def attribute(name, options={})
  # If present but false-y, make sure it is removed anyway so it
  # doesn't confuse ParamsValidate.
  if options.delete(:option_collector)
    option_collector_attribute(name, options)
  else
    super
  end
end

.option_collector_attribute(name, default: {}) ⇒ Object

Define an option collector attribute. Normally used via attribute.

Parameters:

  • name (String, Symbol)

    Name of the attribute to define.

  • default (Object) (defaults to: {})

    Default value for the options.

Since:

  • 1.0.0



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/poise/helpers/option_collector.rb', line 84

def option_collector_attribute(name, default: {})
  # Unlike LWRPBase.attribute, I don't care about Ruby 1.8. Worlds tiniest violin.
  define_method(name.to_sym) do |arg=nil, &block|
    iv_sym = :"@#{name}"

    value = instance_variable_get(iv_sym) || begin
      default = instance_eval(&default) if default.is_a?(Chef::DelayedEvaluator) # Handle lazy{}
      Mash.new(default) # Wrap in a mash because fuck str vs sym.
    end
    if arg
      raise Exceptions::ValidationFailed, "Option #{name} must be a Hash" if arg && !arg.is_a?(Hash)
      # Should this and the update below be a deep merge?
      value.update(arg)
    end
    if block
      ctx = OptionEvalContext.new(self)
      ctx.instance_exec(&block)
      value.update(ctx._options)
    end
    instance_variable_set(iv_sym, value)
    value
  end
end