Class: Class
- Inherits:
-
Object
- Object
- Class
- Defined in:
- lib/constructor.rb
Overview
:nodoc:#
Instance Method Summary collapse
- #constructor(*attrs, &block) ⇒ Object
-
#constructor_block ⇒ Object
:nodoc:#.
-
#constructor_keys ⇒ Object
Access the constructor keys for this class.
Instance Method Details
#constructor(*attrs, &block) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/constructor.rb', line 4 def constructor(*attrs, &block) call_block = '' if block_given? @constructor_block = block call_block = 'self.instance_eval(&self.class.constructor_block)' end # Look for embedded options in the listing: opts = attrs.find { |a| a.kind_of?(Hash) and attrs.delete(a) } do_acc = opts.nil? ? false : opts[:accessors] == true do_reader = opts.nil? ? false : opts[:readers] == true require_args = opts.nil? ? true : opts[:strict] != false super_args = opts.nil? ? nil : opts[:super] # Incorporate superclass's constructor keys, if our superclass if superclass.constructor_keys similar_keys = superclass.constructor_keys & attrs raise "Base class already has keys #{similar_keys.inspect}" unless similar_keys.empty? attrs = [attrs,superclass.constructor_keys].flatten end # Generate ivar assigner code lines assigns = '' attrs.each do |k| assigns += "@#{k.to_s} = args[:#{k.to_s}]\n" end # If accessors option is on, declare accessors for the attributes: if do_acc add_accessors = "attr_accessor " + attrs.reject {|x| superclass.constructor_keys.include?(x.to_sym)}.map {|x| ":#{x.to_s}"}.join(',') #add_accessors = "attr_accessor " + attrs.map {|x| ":#{x.to_s}"}.join(',') self.class_eval add_accessors end # If readers option is on, declare readers for the attributes: if do_reader self.class_eval "attr_reader " + attrs.reject {|x| superclass.constructor_keys.include?(x.to_sym)}.map {|x| ":#{x.to_s}"}.join(',') end # If user supplied super-constructor hints: super_call = '' if super_args list = super_args.map do |a| case a when String %|"#{a}"| when Symbol %|:#{a}| end end super_call = %|super(#{list.join(',')})| end # If strict is on, define the constructor argument validator method, # and setup the initializer to invoke the validator method. # Otherwise, insert lax code into the initializer. validation_code = "return if args.nil?" if require_args self.class_eval do def _validate_constructor_args(args) # First, make sure we've got args of some kind unless args and args.keys and args.keys.size > 0 raise ConstructorArgumentError.new(self.class.constructor_keys) end # Scan for missing keys in the argument hash a_keys = args.keys missing = [] self.class.constructor_keys.each do |ck| unless a_keys.member?(ck) missing << ck end a_keys.delete(ck) # Delete inbound keys as we address them end if missing.size > 0 || a_keys.size > 0 raise ConstructorArgumentError.new(missing,a_keys) end end end # Setup the code to insert into the initializer: validation_code = "_validate_constructor_args args " end # Generate the initializer code self.class_eval %{ def initialize(args=nil) #{super_call} #{validation_code} #{assigns} setup if respond_to?(:setup) #{call_block} end } # Remember our constructor keys @_ctor_keys = attrs end |
#constructor_block ⇒ Object
:nodoc:#
102 103 104 |
# File 'lib/constructor.rb', line 102 def constructor_block #:nodoc:# @constructor_block end |
#constructor_keys ⇒ Object
Access the constructor keys for this class
100 |
# File 'lib/constructor.rb', line 100 def constructor_keys; @_ctor_keys ||=[]; end |