diff options
Diffstat (limited to 'lib/object_builder.rb')
-rw-r--r-- | lib/object_builder.rb | 113 |
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 + + |