Permalink
Browse files

add autoinit.rb

  • Loading branch information...
1 parent adab50d commit 4888bc83ca545a603dddc01bdcac8ea14a4955ff @quix committed Aug 9, 2009
Showing with 455 additions and 0 deletions.
  1. +1 −0 lib/quix.rb
  2. +2 −0 lib/quix/ext/class.rb
  3. +108 −0 lib/quix/ext/class/autoinit.rb
  4. +26 −0 lib/quix/temp_method.rb
  5. +318 −0 test/class_test.rb
View
@@ -1,5 +1,6 @@
require 'quix/ext/array'
+require 'quix/ext/class'
require 'quix/ext/dir'
require 'quix/ext/enumerable'
require 'quix/ext/file'
View
@@ -0,0 +1,2 @@
+
+require 'quix/ext/class/autoinit'
@@ -0,0 +1,108 @@
+
+require 'quix/temp_method'
+
+class Class
+
+ #
+ # autoinit is found in Gavin Sinclair's extensions package. The
+ # following is my own implementation which does not use eval().
+ #
+ # autoinit_options and other methods are contrariwise unique to this
+ # package.
+ #
+ def autoinit(*names, &block)
+ # TODO: jettison 1.8.6; use |&block|
+
+ if block and not [-1, 0].include?(block.arity)
+ raise ArgumentError, "autoinit block must have no arguments"
+ end
+
+ define_method :initialize do |*values|
+ unless values.size == names.size
+ raise ArgumentError,
+ "wrong number of arguments (#{values.size} for #{names.size})"
+ end
+ names.zip(values) { |name, value|
+ instance_variable_set("@#{name}", value)
+ }
+ if block
+ Quix::TempMethod.call_temp_method(self, :__autoinit, &block)
+ end
+ end
+ end
+
+ def autoinit_options(*keys, &block)
+ # TODO: jettison 1.8.6; use |&block|
+
+ define_method :initialize do |*args|
+ options = args.last.is_a?(Hash) ? args.pop : Hash.new
+ expected_args_size = (
+ if block.nil?
+ 0
+ elsif block.arity == -1
+ :any
+ else
+ block.arity
+ end
+ )
+ case expected_args_size
+ when :any, args.size
+ # ok
+ else
+ raise ArgumentError,
+ "wrong number of arguments (#{args.size} for #{expected_args_size})"
+ end
+ keys.zip(options.values_at(*keys)) { |key, value|
+ instance_variable_set("@#{key}", value)
+ }
+ if block
+ Quix::TempMethod.
+ call_temp_method(self, :__autoinit_options, *args, &block)
+ end
+ end
+ end
+
+ #
+ # TODO: jettison 1.8.6; use |&block|
+ #
+ #["", "_options"].each { |infix|
+ # %w[reader writer accessor].each { |suffix|
+ # base = "autoinit#{infix}"
+ # define_method "#{base}_#{suffix}" do |*args, &block|
+ # send("attr_#{suffix}", *args)
+ # send(base, *args, &block)
+ # end
+ # }
+ #}
+ #
+
+ def autoinit_reader(*names, &block)
+ attr_reader(*names)
+ autoinit(*names, &block)
+ end
+
+ def autoinit_options_reader(*keys, &block)
+ attr_reader(*keys)
+ autoinit_options(*keys, &block)
+ end
+
+ def autoinit_writer(*names, &block)
+ attr_writer(*names)
+ autoinit(*names, &block)
+ end
+
+ def autoinit_options_writer(*keys, &block)
+ attr_writer(*keys)
+ autoinit_options(*keys, &block)
+ end
+
+ def autoinit_accessor(*names, &block)
+ attr_accessor(*names)
+ autoinit(*names, &block)
+ end
+
+ def autoinit_options_accessor(*keys, &block)
+ attr_accessor(*keys)
+ autoinit_options(*keys, &block)
+ end
+end
View
@@ -0,0 +1,26 @@
+
+require 'quix/symbol_generator'
+
+module Quix
+ module TempMethod
+ module_function
+
+ def with_temp_method(instance, method_prefix, method_block)
+ method_name = "#{method_prefix}[#{SymbolGenerator.gensym}]"
+ (class << instance ; self ; end).class_eval do
+ define_method(method_name, &method_block)
+ begin
+ yield method_name
+ ensure
+ remove_method(method_name)
+ end
+ end
+ end
+
+ def call_temp_method(instance, method_prefix, *args, &method_block)
+ with_temp_method(instance, method_prefix, method_block) { |method_name|
+ instance.send(method_name, *args)
+ }
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit 4888bc8

Please sign in to comment.