module Poise::Helpers::OptionCollector::ClassMethods

@!classmethods

Public Instance Methods

attribute(name, options={}) click to toggle source

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

Calls superclass method
# File lib/poise/helpers/option_collector.rb, line 79
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
included(klass) click to toggle source
Calls superclass method
# File lib/poise/helpers/option_collector.rb, line 135
def included(klass)
  super
  klass.extend(ClassMethods)
end
option_collector_attribute(name, default: {}, parser: nil, forced_keys: Set.new) click to toggle source

Define an option collector attribute. Normally used via {.attribute}.

@param name [String, Symbol] Name of the attribute to define. @param default [Hash] Default value for the options. @param parser [Proc, Symbol] Optional parser method. If a symbol it is

called as a method on self. Takes a non-hash value and returns a
hash of its parsed representation.

@param forced_keys [Array<Symbol>, Set<Symbol>] Method names that will be forced

to be options rather than calls to the parent resource.
# File lib/poise/helpers/option_collector.rb, line 98
def option_collector_attribute(name, default: {}, parser: nil, forced_keys: Set.new)
  raise Poise::Error.new("Parser must be a Proc or Symbol: #{parser.inspect}") if parser && !(parser.is_a?(Proc) || parser.is_a?(Symbol))
  # Cast to a set at definition time.
  forced_keys = Set.new(forced_keys) unless forced_keys.is_a?(Set)
  # Never allow name to be called accidentally since it does really wonky things.
  forced_keys.add(:name)
  # 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
      if !arg.is_a?(Hash) && parser
        arg = case parser
              when Proc
                instance_exec(arg, &parser)
              when Symbol
                send(parser, arg)
              end
      end
      raise Exceptions::ValidationFailed, "Option #{name} must be a Hash" if !arg.is_a?(Hash)
      # Should this and the update below be a deep merge?
      value.update(arg)
    end
    if block
      ctx = OptionEvalContext.new(self, forced_keys)
      ctx.instance_exec(&block)
      value.update(ctx._options)
    end
    instance_variable_set(iv_sym, value)
    value
  end
end