Class: Stick::Units::Converter
- Inherits:
-
Object
- Object
- Stick::Units::Converter
- Defined in:
- lib/stick/units.rb,
lib/stick/currency.rb,
lib/stick/units/base.rb,
lib/stick/units/loaders.rb,
lib/stick/units/currency.rb
Overview
This class handles all conversions between units.
There are two kinds of units; those that are not expressed as a function of other units –called base units– and those that are expressed as a function of other units –called derived units. The latter kind is registered specifying how it depends on other units, while the former kind is not.
This class also registers a list of Converters that are generally useable. The default Converter which is used when none is specified, can be retrieved with Converter.current. Converters can be registered with Converter.register.
Converters can be loaded from YAML. This allows Converters to be specified in configuration files.
Defined Under Namespace
Classes: Conversion, ExchangeRate, ShiftedConversion
Constant Summary collapse
- THREAD_REFERENCE =
'Units::converter'.to_sym
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
Returns the name of this Converter, or
nil
if the Converter is not registered.
Class Method Summary collapse
-
.coerce_units(unit1, unit2) ⇒ Object
:nodoc:.
- .convert_conversion(units, multiplier = nil) ⇒ Object
-
.converter(name, &blk) ⇒ Object
Returns the converter with the given name.
- .converters ⇒ Object
-
.current ⇒ Object
Returns the current Converter in the current Thread.
-
.register_loader(loader) ⇒ Object
def load(file) load_config(file, self) end.
-
.registered_converters ⇒ Object
Returns the list of names of registered converters.
- .require(file) ⇒ Object
-
.simplify_unit(unit) ⇒ Object
:nodoc:.
-
.with_converter(conv) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#base_unit(name) ⇒ Object
Returns the base unit with this name.
-
#include(conv) ⇒ Object
Included the given converter in the receiver, unless it was already included.
-
#included_converters(result = []) ⇒ Object
Returns the list of all included converters.
-
#includes?(conv) ⇒ Boolean
Returns whether the given converter was included in the receiver.
-
#initialize(name) ⇒ Converter
constructor
Creates a new Converter.
- #load(file) ⇒ Object
- #method_missing(m, *args, &blk) ⇒ Object
-
#registered?(unit) ⇒ Boolean
Checks whether the unit with the given name is registered.
-
#registered_units ⇒ Object
Returns the list of registered unit names as symbols.
-
#to_s ⇒ Object
(also: #inspect)
Returns a human readable string representation of this Converter.
Constructor Details
#initialize(name) ⇒ Converter
Creates a new Converter. If a block is given, it is executed in the newly created Converter’s context.
668 669 670 671 672 |
# File 'lib/stick/units/base.rb', line 668 def initialize(name) @conversions = {} @included = [] @name = name end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(m, *args, &blk) ⇒ Object
729 730 731 732 733 734 735 736 737 |
# File 'lib/stick/units/base.rb', line 729 def method_missing(m, *args, &blk) if registered?(m) raise ::ArgumentError, "Wrong number of arguments" if args.length != 0 return Units::Unit.new({m => 1}, self) end ::Exception.with_clean_backtrace("method_missing") { super } end |
Instance Attribute Details
#name ⇒ Object
Returns the name of this Converter, or nil
if the Converter is not registered.
663 664 665 |
# File 'lib/stick/units/base.rb', line 663 def name @name end |
Class Method Details
.coerce_units(unit1, unit2) ⇒ Object
:nodoc:
909 910 911 |
# File 'lib/stick/units/base.rb', line 909 def coerce_units(unit1, unit2) # :nodoc: [convert_conversion(unit1.units), convert_conversion(unit2.units)] end |
.convert_conversion(units, multiplier = nil) ⇒ Object
918 919 920 921 922 923 924 925 926 927 928 929 930 |
# File 'lib/stick/units/base.rb', line 918 def convert_conversion(units, multiplier = nil) multiplier ||= 1 base_units = {} other_units = {} units.each_pair do |u, e| (u.conversion != :none ? other_units : base_units)[u] = e end result = Conversion.new(Units::Unit.new(base_units, self), multiplier) other_units.each_pair do |u, e| result *= (u.conversion ** e) end result end |
.converter(name, &blk) ⇒ Object
Returns the converter with the given name. This name can be a Symbol or a String.
883 884 885 886 887 888 889 |
# File 'lib/stick/units/base.rb', line 883 def converter(name, &blk) if blk (converters[name.to_sym] ||= new(name.to_sym)).instance_eval(&blk) else converters[name.to_sym] or raise ::ArgumentError, "No converter #{name.to_s.dump} found" end end |
.converters ⇒ Object
932 933 934 |
# File 'lib/stick/units/base.rb', line 932 def converters @converters ||= {} end |
.current ⇒ Object
Returns the current Converter in the current Thread. The default converter is the one returned by converter(:default)
. See also Units#with_converter and Converter.converter.
858 859 860 |
# File 'lib/stick/units/base.rb', line 858 def current Thread.current[THREAD_REFERENCE] ||= converter(:default) end |
.register_loader(loader) ⇒ Object
def load(file)
load_config(file, self)
end
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/stick/units/loaders.rb', line 49 def register_loader(loader) loaders[loader] ||= loader loader.handles.each do |h| loader_hash[h] ||= begin eval %{ module_eval do def #{h}(*a, &b) self.class.send(:loader_hash)[#{h.inspect}].#{h}(self, *a, &b) end end } loader end end @loader_hash end |
.registered_converters ⇒ Object
Returns the list of names of registered converters.
905 906 907 |
# File 'lib/stick/units/base.rb', line 905 def registered_converters converters.keys end |
.require(file) ⇒ Object
38 39 40 41 42 43 |
# File 'lib/stick/units/loaders.rb', line 38 def require(file) @required_configs[file] ||= begin load_config(file + ".rb", self) true end end |
.simplify_unit(unit) ⇒ Object
:nodoc:
913 914 915 916 |
# File 'lib/stick/units/base.rb', line 913 def simplify_unit(unit) # :nodoc: conv = convert_conversion(unit.units) [conv[:multiplier], conv[:units]] end |
.with_converter(conv) ⇒ Object
:nodoc:
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 |
# File 'lib/stick/units/base.rb', line 862 def with_converter(conv) # :nodoc: conv = converter(conv) if not conv.is_a? Units::Converter raise ::ArgumentError, "Converter expected" if not conv.is_a? Units::Converter begin old_conv = Thread.current[THREAD_REFERENCE] if old_conv new_conv = Converter.send(:new, nil) new_conv.include(old_conv) new_conv.include(conv) else new_conv = conv end Thread.current[THREAD_REFERENCE] = new_conv yield ensure Thread.current[THREAD_REFERENCE] = old_conv end end |
Instance Method Details
#base_unit(name) ⇒ Object
Returns the base unit with this name
716 717 718 719 720 721 |
# File 'lib/stick/units/base.rb', line 716 def base_unit(name) if conv = registered?(name) return Units::BaseUnit.new(name, conv) end raise "unit #{name.to_s.dump} not registered with #{self}" end |
#include(conv) ⇒ Object
Included the given converter in the receiver, unless it was already included.
676 677 678 679 680 681 |
# File 'lib/stick/units/base.rb', line 676 def include(conv) conv = Units::Converter.converter(conv) if not conv.is_a?(Units::Converter) raise "Circular include" if conv.includes?(self) @included << conv if not includes? conv self end |
#included_converters(result = []) ⇒ Object
Returns the list of all included converters. This list may contain duplicates in some cases.
696 697 698 699 700 |
# File 'lib/stick/units/base.rb', line 696 def included_converters(result = []) result << self @included.reverse_each { |c| c.included_converters(result) } result end |
#includes?(conv) ⇒ Boolean
Returns whether the given converter was included in the receiver.
685 686 687 688 689 690 691 692 |
# File 'lib/stick/units/base.rb', line 685 def includes?(conv) conv = Units::Converter.converter(conv) if not conv.is_a?(Units::Converter) return true if conv == self @included.each do |c| return true if conv == c || c.includes?(conv) end false end |
#load(file) ⇒ Object
83 84 85 |
# File 'lib/stick/units/loaders.rb', line 83 def load(file) self.class.send(:load_config, file, self) end |
#registered?(unit) ⇒ Boolean
Checks whether the unit with the given name is registered. The name can be a symbol or a string.
704 705 706 707 708 709 710 711 712 713 |
# File 'lib/stick/units/base.rb', line 704 def registered?(unit) unit = unit.to_sym return self if registered_here?(unit) @included.reverse_each do |c| if res = c.registered?(unit) return res end end nil end |
#registered_units ⇒ Object
Returns the list of registered unit names as symbols.
724 725 726 |
# File 'lib/stick/units/base.rb', line 724 def registered_units @conversions.keys end |
#to_s ⇒ Object Also known as: inspect
Returns a human readable string representation of this Converter.
740 741 742 |
# File 'lib/stick/units/base.rb', line 740 def to_s (@name.to_s if @name) || "#<Converter:#{object_id.to_s(16)}>" end |