class ZTK::DSL::Base

Generic Domain-specific Language Interface

This module allows you to easily add attributes and relationships to classes to create a custom DSL in no time.

You can then access these classes in manners similar to what ActiveRecord provides for relationships. You can easily link classes together; load stored objects from Ruby rb files (think Opscode Chef DSL).

I intend the interface to act like ActiveRecord for the programmer and a nice DSL for the end user. It's not meant to be a database; more like a soft dataset in memory; extremely fast but highly volitale. As always you can never have your cake and eat it too.

You specify the “schema” in the classes itself; there is no data storage at this time, but I do plan to add support for loading/saving datasets to disk. Keep in mind since you do not specify type constrants in Ruby, one can assign any object to an attribute.

At this time if you do not specify an ID; one is auto generated.

If you wish to create objects in a nested fashion the outer most object must be started using the class name initializer. Once inside the block you can start using the relationship names and do not need to call any further class initializers.

You can also instantiate classes separately and associate them after the fact. That is not shown in this example.

@example Building infrastructure DSL objects

class Network < ZTK::DSL::Base
  has_many :servers

  attribute :name
  attribute :gw
  attribute :network
  attribute :netmask
end

class Server < ZTK::DSL::Base
  belongs_to :network

  attribute :name
end

Network.new do
  id :leet_net
  name "leet-net"
  gw "7.3.3.1"
  network "7.3.3.0"
  netmask "255.255.255.0"

  server do
    name "leet-server"
  end

  server do
    id :my_server
    name "my-server"
  end

  server do
    name "dev-server"
  end
end

Network.count
Network.all
Network.find(:leet_net)

Server.count
Server.all
Server.find(:my_server)

@author Zachary Patten <zpatten AT jovelabs DOT io>

Public Class Methods

extended(base) click to toggle source

@api private

# File lib/ztk/dsl/base.rb, line 96
def self.extended(base)
  # NOOP
end
included(base) click to toggle source

@api private

# File lib/ztk/dsl/base.rb, line 91
def self.included(base)
  # NOOP
end
inherited(base) click to toggle source

@api private

# File lib/ztk/dsl/base.rb, line 83
def self.inherited(base)
  base.send(:extend, ZTK::DSL::Base::ClassMethods)
  base.instance_eval do
    attribute :id
  end
end
new(id=nil, &block) click to toggle source
# File lib/ztk/dsl/base.rb, line 100
def initialize(id=nil, &block)
  self.id = (id || self.class.next_id)
  self.class.dataset << self

  do_block(&block)
end

Public Instance Methods

do_block(&block) click to toggle source
# File lib/ztk/dsl/base.rb, line 107
def do_block(&block)
  if block_given?
    if (block.arity < 1)
      instance_eval(&block)
    else
      block.call(self)
    end
  end

  if (self.class.dataset.count{ |data| (data.id == self.id) } > 1)
    raise StandardError, "Primary key '#{self.id}' already exists!"
  end
end
inspect() click to toggle source

Instance Inspect

Inspect the DSL object's instance, returning a concise string representation of the instance.

@return [String] A concise string representation of the instance.

# File lib/ztk/dsl/base.rb, line 127
def inspect
  details = Array.new
  details << "attributes=#{attributes.inspect}" if attributes.count > 0
  details << "has_many_references=#{@has_many_references.count}" if @has_many_references
  details << "belongs_to_references=#{@belongs_to_references.count}" if @belongs_to_references
  "#<#{self.class.to_s} id=#{self.id.inspect} #{details.join(', ')}>"
end