aboutsummaryrefslogtreecommitdiff
path: root/lib/object_builder.rb
diff options
context:
space:
mode:
authorPatrick J Cherry <patrick@bytemark.co.uk>2011-04-13 17:03:16 +0100
committerPatrick J Cherry <patrick@bytemark.co.uk>2011-04-13 17:03:16 +0100
commit89a67770e66d11740948e90a41db6cee0482cf8e (patch)
treebe858515fb789a89d68f94975690ab019813726c /lib/object_builder.rb
new version.
Diffstat (limited to 'lib/object_builder.rb')
-rw-r--r--lib/object_builder.rb113
1 files changed, 113 insertions, 0 deletions
diff --git a/lib/object_builder.rb b/lib/object_builder.rb
new file mode 100644
index 0000000..7cb808c
--- /dev/null
+++ b/lib/object_builder.rb
@@ -0,0 +1,113 @@
+# ObjectBuilder is a class to help you build Ruby-based configuration syntaxes.
+# You can use it to make "builder" classes to help build particular types
+# of objects, typically translating simple command-based syntax to creating
+# classes and setting attributes. e.g. here is a description of a day at
+# the zoo:
+#
+# person "Alice"
+# person "Matthew"
+#
+# zoo("London") {
+# enclosure("Butterfly House") {
+#
+# has_roof
+# allow_visitors
+#
+# animals("moth", 10) {
+# wings 2
+# legs 2
+# }
+#
+# animals("butterfly", 200) {
+# wings 2
+# legs 2
+# }
+# }
+#
+# enclosure("Aquarium") {
+# no_roof
+#
+# animal("killer whale") {
+# called "Shamu"
+# wings 0
+# legs 0
+# tail
+# }
+# }
+# }
+#
+# Here is the basic builder class for a Zoo...
+#
+# TODO: finish this convoluted example, if it kills me
+#
+class ObjectBuilder
+ class BuildException < Exception; end
+
+ attr_reader :result
+
+ def initialize(context, *args)
+ @context = context
+ builder_setup(*args)
+ end
+
+ def anonymous_name
+ @@sequence ||= 0 # not inherited, don't want it to be
+ @@sequence += 1
+ "anon.#{Time.now.to_i}.#{@@sequence}"
+ end
+
+ class << self
+
+ def is_builder(word, clazz)
+ define_method(word.to_sym) do |*args, &block|
+ builder = clazz.new(*([@context] + args))
+ builder.instance_eval(&block) if block
+ ["created_#{word}", "created"].each do |created_method|
+ created_method = created_method.to_sym
+ if respond_to?(created_method)
+ __send__(created_method, builder.result)
+ break
+ end
+ end
+ end
+ end
+
+ # FIXME: implement is_builder_deferred to create object at end of block?
+
+ def is_block_attribute(word)
+ define_method(word.to_sym) do |*args, &block|
+ @result.__send__("#{word}=".to_sym, block)
+ end
+ end
+
+ def is_attribute(word)
+ define_method(word.to_sym) do |*args, &block|
+ @result.__send__("#{word}=".to_sym, args[0])
+ end
+ end
+
+ def is_flag_attribute(word)
+ define_method(word.to_sym) do |*args, &block|
+ @result.__send__("#{word}=".to_sym, true)
+ end
+ end
+
+ def load(file)
+ builder = self.new
+ builder.instance_eval(File.read(file), file)
+ builder.result
+ end
+
+ def inherited(*args)
+ initialize_class
+ end
+
+ def initialize_class
+ @words = {}
+ end
+ end
+
+ initialize_class
+end
+
+