require 'metaid' class Object def solidify self end end class Range def solidify to_a.sort_by {|x| rand}.fetch(0) end end module Prototyping def new instance = self.class.allocate instance.class.instance_variable_get(:@prototype_copy).each do |var| instance.instance_variable_set :"@#{var}", instance_variable_get(:"@#{var}") end instance.class.instance_variable_get(:@prototype_solidify).each do |var| instance.instance_variable_set :"@#{var}", instance_variable_get(:"@#{var}").solidify end instance end module Meta def copy *names @prototype_copy ||= [] names.each do |name| @prototype_copy << name end end def solidify *names @prototype_solidify ||= [] names.each do |name| @prototype_solidify << name end end end def self.append_features klass super klass.meta_eval {include Meta} end end class Person include Prototyping attr_reader :name, :age, :strength copy :name, :age solidify :strength def initialize name, age, strength @name, @age, @strength = name, age, strength end end # Create a new instance of Person to be used as a prototype scott_prototype = Person.new("Scott", 17, 1 .. 2) puts scott_prototype.inspect # # # Create a new instance of Person from the prototype # Copies or "solidify"s instance variables depending on the class definition # In this case, solidifies the range @strength scott_instance = scott_prototype.new puts scott_instance.inspect # Either: # # # or # #