lib/cog/dsl/seed_dsl.rb

Summary

Maintainability
A
55 mins
Test Coverage
module Cog
  module DSL
    
    # DSL for defining cog seeds
    class SeedDSL
      
      # @api developer
      # @return [Cog::Seed] the seed which is defined by this DSL object
      attr_reader :seed
      
      # @api developer
      def initialize(name)
        @seed = Cog::Seed.new name
      end
      
      # Place classes generated by this seed in the given scope
      # @param name [String] name of the scope
      # @return [nil]
      def in_scope(name)
        seed_eval { @in_scope = name.to_s }
        nil
      end
      
      def constructor(&block)
        feature :constructor, &block
      end
      
      def destructor(&block)
        feature :destructor, &block
      end
      
      # @api developer
      def method_missing(meth, *args, &block)
        meth = meth.to_s
        if meth.end_with? '_feature'
          opt = args.last.is_a?(Hash) ? args.pop : {}
          if /(?:\b|_)(public|protected|private)(?:\b|_)/ =~ meth
            opt[:access] = $1.to_sym
          end
          if /(?:\b|_)(abstract|virtual)(?:\b|_)/ =~ meth
            opt[$1.to_sym] = true
          end
          args << opt
          feature(*args, &block)
        else
          super
        end
      end
      
      # Define a new feature for this seed
      # @param name [String] name of the feature
      # @option opt [Symbol] :access (:private) one of `:public`, `:protected`, or `private`
      # @option opt [Boolean] :abstract (false) is this an abstract feature? If so, no implementation will be generated
      # @option opt [Boolean] :virtual (false) is this a virtual feature? Virtual features can be replaced in subclasses
      # @yieldparam f [FeatureDSL] use this to further specify the feature
      # @return [nil]
      def feature(name, opt={}, &block)
        dsl = FeatureDSL.new @seed, name, opt
        block.call dsl unless block.nil?
        f = dsl.feature
        seed_eval { @features << f }
        nil
      end
      
      private
      
      def seed_eval(&block)
        @seed.instance_eval &block
      end
    end
  end
end