module Alki::ClassBuilder
Public Class Methods
build(data)
click to toggle source
# File lib/alki/class_builder.rb, line 20 def build(data) class_name = data[:constant_name] if !class_name && data[:name] class_name = Alki::Support.classify(data[:name]) end klass = find_or_create_class(class_name, data) build_class data, klass if data[:secondary_classes] build_secondary_classes data[:secondary_classes], klass end klass end
create_constant(name,value = Class.new, parent=nil)
click to toggle source
# File lib/alki/class_builder.rb, line 7 def create_constant(name,value = Class.new, parent=nil) parent ||= Object *ans, ln = name.to_s.split('::') ans.each do |a| unless parent.const_defined? a parent.const_set a, Module.new end parent = parent.const_get a end parent.const_set ln, value end
Private Class Methods
add_initialize(klass,params)
click to toggle source
# File lib/alki/class_builder.rb, line 144 def add_initialize(klass,params) at_setters = '' params.each do |p| p,default = p.is_a?(Array) ? p : [p,nil] if default default_method = "_default_#{p}".to_sym klass.send(:define_method, default_method, &default) klass.send :private, default_method at_setters << "@#{p} = #{p} || #{default_method}\n" else at_setters << "@#{p} = #{p}\n" end end klass.class_eval " def initialize(#{params.map{|p| p.is_a?(Array) ? "#{p[0]}=nil" : p.to_s}.join(', ')}) #{at_setters}end" end
add_methods(klass, data)
click to toggle source
# File lib/alki/class_builder.rb, line 117 def add_methods(klass, data) if data[:class_methods] data[:class_methods].each do |name, method| klass.define_singleton_method name, &method[:body] klass.singleton_class.send :private, name if method[:private] end end if data[:instance_methods] data[:instance_methods].each do |name, method| klass.send :define_method, name, &method[:body] klass.send :private, name if method[:private] end end if data[:delegators] klass.extend Forwardable data[:delegators].each do |name,delegator| klass.def_delegator delegator[:accessor], delegator[:method], name end end klass.send :attr_reader, *data[:attr_readers] if data[:attr_readers] klass.send :attr_writer, *data[:attr_writers] if data[:attr_writers] klass.send :attr_accessor, *data[:attr_accessors] if data[:attr_accessors] end
build_class(data,klass)
click to toggle source
# File lib/alki/class_builder.rb, line 91 def build_class(data,klass) if data[:module] if module_not_empty? data[:module] klass.include data[:module] end if data[:module].const_defined?(:ClassMethods) && module_not_empty?(data[:module]::ClassMethods) klass.extend data[:module]::ClassMethods end end if data[:modules] data[:modules].each do |mod| klass.include Alki.load mod end end if data[:class_modules] data[:class_modules].each do |mod| klass.extend Alki.load mod end end add_methods klass, data add_initialize klass, data[:initialize_params] if data[:initialize_params] end
build_secondary_classes(secondary_classes, parent_class)
click to toggle source
# File lib/alki/class_builder.rb, line 75 def build_secondary_classes(secondary_classes, parent_class) secondary_classes.each do |data| if data[:subclass] data = data.merge(parent_class: parent_class,constant_name: data[:subclass]) elsif !data[:constant_name] && !data[:name] raise ArgumentError.new("Secondary classes must have names") end build data end end
find_or_create_class(class_name, data)
click to toggle source
# File lib/alki/class_builder.rb, line 39 def find_or_create_class(class_name, data) type = data[:type] || :class klass = Alki::Support.constantize class_name, data[:parent_class] if class_name must_create_constant = !klass && class_name super_class = data[:super_class] ? Alki.load(data[:super_class]) : Object if klass validate_existing_class(type, class_name, klass, super_class) else klass = case type when :module then Module.new when :class then Class.new(super_class) end end if must_create_constant create_constant class_name, klass, data[:parent_class] end klass end
module_not_empty?(mod)
click to toggle source
# File lib/alki/class_builder.rb, line 86 def module_not_empty?(mod) not mod.instance_methods.empty? && mod.private_instance_methods.empty? end
validate_existing_class(type, class_name, klass, super_class)
click to toggle source
# File lib/alki/class_builder.rb, line 61 def validate_existing_class(type, class_name, klass, super_class) if type == :module if klass.class != Module raise "#{class_name} already exists as a #{klass.class}" end elsif type == :class if klass.class != Class raise "#{class_name} already exists as a #{klass.class}" elsif klass.superclass != super_class raise "#{class_name} already exists with different super class" end end end