module Twigg::Settings::DSL::InstanceMethods

Public Class Methods

new(hash = nil) click to toggle source
Calls superclass method
# File lib/twigg/settings/dsl.rb, line 61
def initialize(hash = nil)
  super
  deep_open_structify!(self)
  override_methods!(self, self.class.overrides)
end

Private Instance Methods

deep_open_structify!(instance) click to toggle source

Recursively replace nested hash values with OpenStructs.

This enables us to make nice calls like `Config.foo.bar` instead of the somewhat unsightly `Config.foo`.

# File lib/twigg/settings/dsl.rb, line 71
def deep_open_structify!(instance)
  # call `to_a` here to avoid mutating the collection during iteration
  instance.each_pair.to_a.each do |key, value|
    if value.is_a?(Hash)
      deep_open_structify!(instance.[]=(key, OpenStruct.new(value)))
    end
  end
end
define_getter(instance, namespace, name, options) click to toggle source

Defines a getter on the `instance` for setting `name` within `namespace`.

The getter:

- memoizes its result
- raises an ArgumentError if the option is required by not
  configured
- supplies a default value if the option is not configured and a
  default setting is available
- optionally calls a supplied block to perform validation of the
  configured value
# File lib/twigg/settings/dsl.rb, line 124
def define_getter(instance, namespace, name, options)
  instance.define_singleton_method name do
    value = instance_variable_get("@#{namespace}__#{name}")
    return value if value

    if options[:required] &&
      !instance.each_pair.to_a.map(&:first).include?(name)
      raise ArgumentError, "#{name} not set"
    end

    value = instance.[](name) || options[:default]

    options[:block].call(name, value) if options[:block]

    instance_variable_set("@#{namespace}__#{name}", value)
  end
end
override_methods!(instance, overrides, namespace = nil) click to toggle source

Recurses through the `overrides` hash, overriding OpenStruct-supplied methods with ones which handle defaults, perform validation, and memoize their results.

The `overrides` hash itself is built up using the DSL as this class file is passed. This method is called at runtime, once the YAML file containing the configuration has been loaded from disk.

# File lib/twigg/settings/dsl.rb, line 87
def override_methods!(instance, overrides, namespace = nil)
  return unless overrides

  overrides.each do |name, options|
    if options.is_a?(Namespace)
      process_namespace(instance, namespace, name, options) # recurses
    else
      define_getter(instance, namespace, name, options)
    end
  end
end
process_namespace(instance, namespace, name, options) click to toggle source

Sets up the given `namespace` on `instance`, if not already set up, and (recursively) calls {#override_methods!} to set up `name`.

# File lib/twigg/settings/dsl.rb, line 101
def process_namespace(instance, namespace, name, options)
  nested = instance.[](name)

  unless nested.is_a?(OpenStruct)
    instance.[]=(name, nested = OpenStruct.new)
  end

  override_methods!(nested, options, name)
end