Class: Module

Inherits:
Object show all
Defined in:
lib/mega/macro.rb,
lib/mega/classmethods.rb,
lib/mega/dynamic_mixin.rb,
lib/mega/preinitialize.rb

Overview

:title: Preinitialize

This is an object preinitialize system, which provides an elegant way to initialize an object allowing the class to provide additional default structure to an object prior to calling initialize.

In effect it does two things after allocating the object but prior to initializing it.

First, it calls the class method #default_instance_variables, which returns a hash and by default returns the hash stored in @default_instance_variables. It uses this to pre-define instance variables.

Then it goes to the top of the class hierarchy and works it’s way down calling #preinitialize if defined. WARNING! It is rather useless to use super inside the any preinitialize hook.

class X
  default_instance_variables[:a] = 42

  def preinitialize
    @b = 23
  end
end

x = X.new
x.a         #=> 42
x.b         #=> 23

If neded the original new method has been aliased, albeit postinitialize_new is probably a bit of a misnomer.

Instance Method Summary collapse

Instance Method Details

#append_dynamic_features(base, options) ⇒ Object

Note: Is this the best name for this callback?



68
69
70
71
72
# File 'lib/mega/macro.rb', line 68

def append_dynamic_features( base, options )
  macros.each do |m|
    base.class_eval m.call( options )
  end
end

#append_features(base) ⇒ Object



47
48
49
50
51
52
53
54
# File 'lib/mega/classmethods.rb', line 47

def append_features(base)
  append_features_no_classmethods(base)
  begin clsm = self::ClassMethods
  rescue NameError
    clsm = nil
  end
  base.extend(clsm) if clsm
end

#append_features_no_classmethodsObject



46
# File 'lib/mega/classmethods.rb', line 46

alias_method :append_features_no_classmethods, :append_features

#attr_parameter(*opts) ⇒ Object

Define an instance option method (via hash).



129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/mega/dynamic_mixin.rb', line 129

def attr_parameter( *opts )
  hopts = opts.pop if Hash === opts.last
  opts.each { |k| hopts[k] = nil }
  mod = self
  hopts.each { |key, default|
    self.instance_eval {
      define_method( key ) do
        self.class.module_parameter_get( mod, key ) || default
      end
    }
  }
end

#attr_parameters(meth, defaults = {}) ⇒ Object

Define a group of instance options via a hash.



143
144
145
146
147
148
149
150
# File 'lib/mega/dynamic_mixin.rb', line 143

def attr_parameters( meth, defaults={} )
  mod = self
  self.instance_eval {
    define_method( meth ) do |key|
      self.class.module_parameter_get( mod, key ) || defaults[key]
    end
  }
end

#default_instance_variables(complete = false) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/mega/preinitialize.rb', line 62

def default_instance_variables(complete=false)
  @default_instance_variables ||= {}
  unless complete
    return @default_instance_variables
  else
    parent = ancestors[1]
    if parent
      return @default_instance_variables.merge(parent.default_instance_variables)
    else
      return @default_instance_variables
    end
  end
end

#extend(*args) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/mega/macro.rb', line 76

def extend(*args)
  options = args.last.is_a?(Hash) ? args.pop : {}
  for mod in args
    mod.extend_dynamic_object( self, options )
  end
  extend_without_macros(*args)
end

#extend_dynamic_object(base, options) ⇒ Object

Note: Is this the best name for this callback?



85
86
87
88
89
# File 'lib/mega/macro.rb', line 85

def extend_dynamic_object( base, options )
  macros.each do |m|
    (class << base; self ; end).class_eval m.call( options )
  end
end

#extend_without_macrosObject



74
# File 'lib/mega/macro.rb', line 74

alias_method :extend_without_macros, :extend

#include(*args) ⇒ Object

Alternate include which will store dynamic options.



98
99
100
101
102
103
104
# File 'lib/mega/dynamic_mixin.rb', line 98

def include(*args)
  options = args.last.is_a?(Hash) ? args.pop : {}
  for mod in args
    mod.append_dynamic_features( self, options )
  end
  include_without_macros(*args)
end

#include_without_macrosObject



57
# File 'lib/mega/macro.rb', line 57

alias_method :include_without_macros, :include

#include_without_optionsObject



95
96
97
98
99
100
101
# File 'lib/mega/dynamic_mixin.rb', line 95

def include(*args)
  options = args.last.is_a?(Hash) ? args.pop : {}
  for mod in args
    mod.append_dynamic_features( self, options )
  end
  include_without_macros(*args)
end

#local_parameters(defaults = {}) ⇒ Object

Define a group of local options via a hash.



121
122
123
124
125
126
# File 'lib/mega/dynamic_mixin.rb', line 121

def local_parameters( defaults={} )
  mod = self
  lambda { |key, inst|
    inst.class.module_parameter_get( mod, key ) || defaults[key]
  }
end

#macro(&blk) ⇒ Object



51
52
53
# File 'lib/mega/macro.rb', line 51

def macro( &blk )
  (@macros ||= []) << blk
end

#macrosObject



55
# File 'lib/mega/macro.rb', line 55

def macros ; @macros ||= [] ; end

#module_parameter_get(mod, key) ⇒ Object

Convenice method for looking up a parameter



108
109
110
111
112
113
114
115
116
117
# File 'lib/mega/dynamic_mixin.rb', line 108

def module_parameter_get( mod, key )
  if self.module_parameters.key?(mod)
    self.module_parameters[mod][key]
  else
    anc = self.ancestors[1]
    if anc
      anc.module_parameter_get( mod, key )
    end
  end
end

#module_parametersObject

Store for dynamic module parameters. This is local per module and indexed on module/class included-into.



87
88
89
# File 'lib/mega/dynamic_mixin.rb', line 87

def module_parameters
  @module_parameters ||= {}
end

#module_parameters=(x) ⇒ Object



91
92
93
# File 'lib/mega/dynamic_mixin.rb', line 91

def module_parameters=(x)
  @module_parameters = x
end