···
On Aug 9, 2008, at 5:46 PM, Patrick Li wrote:
string = Farm.create do
barn do
animal "dog"
animal "cat"
end
pond do
animal "whale"
animal "shark"
end
end
The string should print:
Farm contains
[
Barn contains
[
dog
cat
]
Pond contains
[
whale
shark
]
]
It would be really really nice to have this also:
Farm.create do
animal "whale"
end
#
f =
farm {
barn {
animal :dog
animal :cat
}
pond {
animal :whale
animal :shark
}
}
p f
#=> #<Farm:0x250d0 @pond=#<Farm::Pond:0x24e78 @animals=[#<Whale:0x24d74>, #<Shark:0x24d38>]>, @barn=#<Farm::Barn:0x24fe0 @animals=[#<Dog:0x24edc>, #<Cat:0x24ea0>]>>
BEGIN {
# these classe are unimportant
#
class Animal; end
class Dog < Animal; end
class Cat < Animal; end
class Whale < Animal; end
class Shark < Animal; end
# this is important, note how it *wraps* a class so the instance_eval is the
# *dsl* instance_eval, note that of the wrapped object
#
module Dsl
module ClassMethods
def dsl &block
unless @dsl
name = self.name.downcase.split(%r/::/).last
@dsl = (
Class.new do
attr name
const_set :Name, name
def initialize object, &block
ivar = "@#{ self.class.const_get(:Name) }"
instance_variable_set ivar, object
instance_eval &block if block
end
end
)
end
@dsl.module_eval &block if block
@dsl
end
end
module InstanceMethods
def dsl &block
self.class.dsl.new(self, &block)
end
end
def Dsl.included other
other.send :extend, ClassMethods
other.send :include, InstanceMethods
end
end
# again this is mostly unimportant, just note how they make use of the module
# for declaring the dsl class, and how they use it in intiialize
#
class Farm
include Dsl
attr_accessor 'barn'
attr_accessor 'pond'
def initialize &block
dsl &block
end
class Barn
include Dsl
attr_accessor 'animals'
def initialize &block
@animals =
dsl &block
end
dsl {
def animal name
barn.animals << Object.const_get(name.to_s.capitalize).new
end
}
end
class Pond
include Dsl
attr_accessor 'animals'
def initialize &block
@animals =
dsl &block
end
dsl {
def animal name
pond.animals << Object.const_get(name.to_s.capitalize).new
end
}
end
dsl {
def barn *a, &b
farm.barn = Barn.new(*a, &b)
end
def pond *a, &b
farm.pond = Pond.new(*a, &b)
end
}
end
# this is just the top level hook
#
def farm(*a, &b) Farm.new(*a, &b) end
}
a @ http://codeforpeople.com/
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama