Sha256: d041468dd079e29e4d3d6375c1d0ac1d888cc5bb563967df785cea5f637277ed

Contents?: true

Size: 1.47 KB

Versions: 2

Compression:

Stored size: 1.47 KB

Contents

# frozen_string_literal: true

module Nocode
  module Util
    # Add on a DSL for classes.  The DSL allows for a new class-level keyword called 'option'
    # which can be used to describe what metadata values are important.  Then instances
    # can reference those option's values using magic _option methods.  For example:
    #
    # class Animal
    #   include Optionable
    #   option :type
    #   attr_writer :options
    # end
    #
    # animal = Animal.new
    # animal.options = { 'type' => 'dog' }
    #
    # animal.type_option # -> should return 'dog'
    module Optionable
      def self.included(klass)
        klass.extend(ClassMethods)
      end

      # Class-level DSL Methods
      module ClassMethods
        def option(*values)
          values.each { |v| options << v.to_s }
        end

        def options
          @options ||= []
        end
      end

      OPTION_PREFIX = '_option'

      def options
        @options || {}
      end

      def method_missing(name, *args, &block)
        key = option_key(name)

        if name.to_s.end_with?(OPTION_PREFIX) && self.class.options.include?(key)
          options[key]
        else
          super
        end
      end

      def respond_to_missing?(name, include_private = false)
        key = option_key(name)

        (name.to_s.end_with?(OPTION_PREFIX) && self.class.options.include?(key)) || super
      end

      private

      def option_key(name)
        name.to_s.gsub(OPTION_PREFIX, '')
      end
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
nocode-0.0.5 lib/nocode/util/optionable.rb
nocode-0.0.4 lib/nocode/util/optionable.rb