require 'units/units' class Object # :nodoc: alias :method_missing_before_units :method_missing def method_missing(method,*args) begin s = method.to_s.split('_') if s.select{|e| e == 'per'}.size > 0 per_ratio method, args elsif s.select{|e| e == 'in'}.size > 0 per_ratio method.to_s.sub(/_in_/,'_per_').to_sym, args else convert_unit_value method, args end rescue Exception => exception method_missing_before_units method, args end end def convert_unit_value(method,*args) if Units.defining? reference = Units.make_forward_reference(method,Units.defining?) begin value = Units.convert 1, method Units.release_forward_reference reference value rescue MissingUnitsException Units.hold_forward_reference rescue UnitsException => exception units_problem("definition",exception,method,args) rescue Exception => exception method_missing_before_units(method,args) end else begin Units.convert 1, method rescue UnitsException => exception units_problem("use",exception,method,args) rescue Exception method_missing_before_units(method,args) end end end def per_ratio(method,*args) if Units.defining? reference = Units.make_forward_reference(method,Units.defining?) begin value = convert_per_ratio method Units.release_forward_reference reference value rescue MissingUnitsException Units.hold_forward_reference rescue UnitsException => exception units_problem("definition",exception,method,args) rescue Exception method_missing_before_units(method,args) end else convert_per_ratio method end end def convert_per_ratio(method) ps = method.to_s.split '_per_' raise UnitsException('invalid per method') if ps.size != 2 value = (1.unite ps[1]) / (1.unite ps[0]) raise UnitsException.new("per ratio has units") if value.kind_of? NumericWithUnits value end def units_problem(state,exception,method,args) raise exception end end