alchemist 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 09cdd7bc72d33ef49f70bfa21e7a6b98bc56ca35
4
- data.tar.gz: 5930f598e0adec3f2a8b3e3e2030fd61b9c48234
3
+ metadata.gz: f47215664aef5b08025bbf14fcb971c7b3d8d726
4
+ data.tar.gz: 92dcc4243340af6f1e4cacfb9593f292a8fdf16c
5
5
  SHA512:
6
- metadata.gz: 72133a2fa6b707b2e52e6cb5354506d364b176aaab25383b9db8f341be847fa2622a89e888fc3adeb8021f2e347b210961a2fca687d4278a5807da5d41827bc0
7
- data.tar.gz: b6ded515a9ebd212ace47ba64a91a9f44619f757457f27a8ae384edf380b327312e5223c444122ae5e3a2552c9d1330964c99e115f88c2e66ac6315f31fc8b3d
6
+ metadata.gz: 6f38ec388bac7cea190f0ace7bca99c2d5da955f4fa6ce4719cbca2cd4df603ccdfb53bc33e8125ff87169d77bb63873fe927c5e42be43b02549802cf163cd39
7
+ data.tar.gz: 085ddcae66c574428f71b8c9c2a2b149144ba80debc5585c88d82723e2bd0c0b96bd2fc71166d1920e2815adc242c989d4e49f59c852093d1bed281153ffb5e2
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- alchemist (0.1.5)
4
+ alchemist (0.1.6)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -2,132 +2,21 @@ require "alchemist/conversion_table"
2
2
  require "alchemist/measurement"
3
3
  require "alchemist/compound_measurement"
4
4
  require "alchemist/module_builder"
5
+ require "alchemist/configuration"
6
+ require "alchemist/library"
5
7
 
6
8
  module Alchemist
7
9
  autoload :Earth, "alchemist/objects/planets/earth"
8
10
 
9
- DATA_DIR = File.join(File.dirname(__FILE__), "alchemist", "data")
10
-
11
- DEFAULT_UNITS_FILE = File.join(DATA_DIR, "units.yml")
12
- DEFAULT_BINARY_PREFIXES_FILE = File.join(DATA_DIR, "binary_prefixes.yml")
13
- DEFAULT_SI_UNITS_FILE = File.join(DATA_DIR, "si_units.yml")
14
- DEFAULT_UNIT_PREFIXES_FILE = File.join(DATA_DIR, "unit_prefixes.yml")
15
-
16
11
  def self.setup category = nil
17
12
  if category
18
13
  Numeric.send(:include, ModuleBuilder.new(category).build)
19
14
  else
20
- conversion_table.keys.each { |category| Numeric.send(:include, ModuleBuilder.new(category).build) }
15
+ library.categories.each { |category| Numeric.send(:include, ModuleBuilder.new(category).build) }
21
16
  end
22
17
  end
23
18
 
24
19
  def self.measure value, unit, exponent = 1.0
25
20
  Measurement.new value, unit, exponent
26
21
  end
27
-
28
- def self.has_measurement? name
29
- conversions.keys.include? name.to_sym
30
- end
31
-
32
- def self.measurement_for name
33
- conversions[ name.to_sym ]
34
- end
35
-
36
- def self.register(type, names, value)
37
- names = Array(names)
38
- value = value.is_a?(Measurement) ? value.base(type) : value
39
- Alchemist.conversion_table[type] ||= {}
40
-
41
- names.each do |name|
42
- conversions[name] ||= []
43
- conversions[name] << type
44
- Alchemist.conversion_table[type][name] = value
45
- end
46
- end
47
-
48
- def self.parse_prefix(unit)
49
- matches = unit.to_s.match(prefix_matcher)
50
- prefix, parsed_unit = matches.captures
51
-
52
- if prefix && si_units.include?(parsed_unit)
53
- value = prefixed_value_for(prefix.to_sym, parsed_unit)
54
- [value, parsed_unit.to_sym]
55
- else
56
- [1, unit]
57
- end
58
- end
59
-
60
- def self.register_operation_conversions type, other_type, operation, converted_type
61
- operator_actions[operation] ||= []
62
- operator_actions[operation] << [type, other_type, converted_type]
63
- end
64
-
65
- def self.operator_actions
66
- @operator_actions ||= {}
67
- end
68
-
69
- def self.binary_prefixes
70
- @binary_prefixes ||= YAML.load_file(DEFAULT_BINARY_PREFIXES_FILE)
71
- end
72
-
73
- def self.si_units
74
- @si_units ||= YAML.load_file(DEFAULT_SI_UNITS_FILE)
75
- end
76
-
77
- def self.unit_prefixes
78
- @unit_prefixes ||= YAML.load_file(DEFAULT_UNIT_PREFIXES_FILE)
79
- end
80
-
81
- def self.use_si
82
- @use_si ||= false
83
- end
84
-
85
- def self.use_si= use_si
86
- @use_si = use_si
87
- end
88
-
89
- def self.load_conversion_table(filename=DEFAULT_UNITS_FILE)
90
- @conversion_table = ConversionTable.new.load_all(filename)
91
- end
92
-
93
- def self.conversion_table
94
- @conversion_table ||= load_conversion_table
95
- end
96
-
97
- def self.conversions
98
- @conversions ||= load_conversions
99
- end
100
-
101
-
102
- private
103
-
104
- def self.use_binary_prefix? unit
105
- !use_si && measurement_for(unit).include?(:information_storage)
106
- end
107
-
108
- def self.prefix_matcher
109
- @prefix_matcher ||= begin
110
- prefix_keys = unit_prefixes.keys.map(&:to_s).sort{ |a,b| b.length <=> a.length }
111
- %r{^(#{prefix_keys.join('|')})?(.+)}
112
- end
113
- end
114
-
115
- def self.prefixed_value_for prefix, unit
116
- if use_binary_prefix? unit
117
- binary_prefixes[prefix]
118
- else
119
- unit_prefixes[prefix]
120
- end
121
- end
122
-
123
- def self.load_conversions
124
- conversions = {}
125
- conversion_table.each do |type, table_conversions|
126
- table_conversions.each do |name, value|
127
- conversions[name] ||= []
128
- conversions[name] << type
129
- end
130
- end
131
- conversions
132
- end
133
22
  end
@@ -42,7 +42,7 @@ module Alchemist
42
42
 
43
43
  def should_remove_units? numerator, denominator
44
44
  return false if numerator.is_a?(Numeric) || denominator.is_a?(Numeric)
45
- (Alchemist.measurement_for(numerator.unit_name) & Alchemist.measurement_for(denominator.unit_name)).length > 0
45
+ (Alchemist.library.measurement_for(numerator.unit_name) & Alchemist.library.measurement_for(denominator.unit_name)).length > 0
46
46
  end
47
47
 
48
48
  def set_coefficients
@@ -56,7 +56,7 @@ module Alchemist
56
56
  end
57
57
 
58
58
  def method_missing(method, *attrs, &block)
59
- if Alchemist.measurement_for(method)
59
+ if Alchemist.library.measurement_for(method)
60
60
  @denominators << Alchemist.measure(1, method)
61
61
  consolidate
62
62
  end
@@ -0,0 +1,26 @@
1
+ require 'singleton'
2
+
3
+ module Alchemist
4
+ def self.config
5
+ Configuration.instance
6
+ end
7
+
8
+ class Configuration
9
+ DATA_DIR = File.join(File.dirname(__FILE__), "data")
10
+ DEFAULT_UNITS_FILE = File.join(DATA_DIR, "units.yml")
11
+ DEFAULT_SI_UNITS_FILE = File.join(DATA_DIR, "si_units.yml")
12
+ DEFAULT_BINARY_PREFIXES_FILE = File.join(DATA_DIR, "binary_prefixes.yml")
13
+ DEFAULT_UNIT_PREFIXES_FILE = File.join(DATA_DIR, "unit_prefixes.yml")
14
+
15
+ include Singleton
16
+
17
+ attr_accessor :use_si
18
+ def initialize
19
+ @use_si = false
20
+ end
21
+
22
+ def use_si?
23
+ @use_si
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,86 @@
1
+ require 'singleton'
2
+
3
+ module Alchemist
4
+ def self.library
5
+ Library.instance
6
+ end
7
+
8
+ class Library
9
+ include Singleton
10
+
11
+ attr_reader :si_units, :unit_prefixes, :conversion_table, :binary_prefixes
12
+
13
+ def initialize
14
+ @conversion_table = load_conversion_table
15
+ @si_units = YAML.load_file(Configuration::DEFAULT_SI_UNITS_FILE)
16
+ @unit_prefixes = YAML.load_file(Configuration::DEFAULT_UNIT_PREFIXES_FILE)
17
+ @binary_prefixes = YAML.load_file(Configuration::DEFAULT_BINARY_PREFIXES_FILE)
18
+ end
19
+
20
+ def categories
21
+ @conversion_table.keys
22
+ end
23
+
24
+ def unit_names category
25
+ @conversion_table[category.to_sym].map { |values| values[0] }
26
+ end
27
+
28
+ def measurement_for unit_name
29
+ conversions[ unit_name.to_sym ]
30
+ end
31
+
32
+ def conversions
33
+ @conversions ||= load_conversions
34
+ end
35
+
36
+ def conversion_base_for(unit_type, unit_name)
37
+ @conversion_table[unit_type][unit_name]
38
+ end
39
+
40
+ def has_measurement? name
41
+ conversions.keys.include? name.to_sym
42
+ end
43
+
44
+ def register_operation_conversions type, other_type, operation, converted_type
45
+ operator_actions[operation] ||= []
46
+ operator_actions[operation] << [type, other_type, converted_type]
47
+ end
48
+
49
+ def operator_actions
50
+ @operator_actions ||= {}
51
+ end
52
+
53
+ def load_conversion_table(filename=Configuration::DEFAULT_UNITS_FILE)
54
+ if new_table = ConversionTable.new.load_all(filename)
55
+ @conversion_table = new_table
56
+ else
57
+ @conversion_table ||= load_conversion_table
58
+ end
59
+ end
60
+
61
+ def register(type, names, value)
62
+ names = Array(names)
63
+ value = value.is_a?(Measurement) ? value.base(type) : value
64
+ conversion_table[type] ||= {}
65
+
66
+ names.each do |name|
67
+ conversions[name] ||= []
68
+ conversions[name] << type
69
+ conversion_table[type][name] = value
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def load_conversions
76
+ conversions = {}
77
+ conversion_table.each do |type, table_conversions|
78
+ table_conversions.each do |name, value|
79
+ conversions[name] ||= []
80
+ conversions[name] << type
81
+ end
82
+ end
83
+ conversions
84
+ end
85
+ end
86
+ end
@@ -18,7 +18,7 @@ module Alchemist
18
18
 
19
19
  def to type = nil
20
20
  if type
21
- convertor.send(type)
21
+ convertor.send(type, exponent)
22
22
  else
23
23
  convertor
24
24
  end
@@ -27,24 +27,28 @@ module Alchemist
27
27
  def + measurement
28
28
  ensure_shared_type!(measurement)
29
29
  converted = measurement.to(unit_name)
30
- Measurement.new(value + converted.value, unit_name, exponent)
30
+ remeasure(value + converted.value)
31
31
  end
32
32
 
33
33
  def - measurement
34
34
  ensure_shared_type!(measurement)
35
35
  converted = measurement.to(unit_name)
36
- Measurement.new(value - converted.value, unit_name, exponent)
36
+ remeasure(value - converted.value)
37
37
  end
38
38
 
39
39
  def / measurement
40
- ensure_shared_type!(measurement)
41
- dividend = measurement.is_a?(Measurement) ? measurement.to(unit_name).to_f / exponent : measurement
42
- Measurement.new(value / dividend, unit_name, exponent).value
40
+ converted = remeasure(value / dividend(measurement))
41
+
42
+ if measurement.is_a?(Measurement)
43
+ converted.value
44
+ else
45
+ converted
46
+ end
43
47
  end
44
48
 
45
49
  def * multiplicand
46
50
  if multiplicand.is_a?(Numeric)
47
- Measurement.new(value * multiplicand, unit_name, exponent)
51
+ remeasure(value * multiplicand)
48
52
  else
49
53
  try_raising_dimension(multiplicand)
50
54
  end
@@ -52,39 +56,68 @@ module Alchemist
52
56
 
53
57
  def base unit_type
54
58
  conversion_base = conversion_base_for(unit_type)
55
- convert_to_base conversion_base
59
+ convert_to_base(conversion_base)
56
60
  end
57
61
 
58
62
  def to_s
59
- value.to_s
63
+ to_f.to_s
60
64
  end
61
65
 
62
66
  def to_i
63
- value.to_i
67
+ to_f.to_i
64
68
  end
65
69
 
66
70
  def to_f
67
- @value
71
+ @value * exponent
68
72
  end
69
73
 
70
74
  def <=>(other)
71
- (self.to_f * exponent).to_f <=> other.to(unit_name).to_f
75
+ self.to_f <=> other.to(unit_name).to_f
72
76
  end
73
77
 
74
78
  def types
75
- Alchemist.measurement_for(unit_name)
79
+ library.measurement_for(unit_name)
76
80
  end
77
81
 
78
82
  def shared_types other_unit_name
79
- types & Alchemist.measurement_for(other_unit_name)
83
+ types & library.measurement_for(other_unit_name)
80
84
  end
81
85
 
82
86
  def coerce(number)
83
87
  [self, number]
84
88
  end
85
89
 
90
+ def round(*args)
91
+ remeasure(value.round(*args))
92
+ end
93
+
94
+ def ceil(*args)
95
+ remeasure(value.ceil(*args))
96
+ end
97
+
98
+ def floor(*args)
99
+ remeasure(value.floor(*args))
100
+ end
101
+
86
102
  private
87
103
 
104
+ def dividend measurement
105
+ if measurement.is_a?(Measurement)
106
+ ensure_shared_type!(measurement)
107
+ measurement.to(unit_name).to_f / exponent
108
+ else
109
+ measurement
110
+ end
111
+ end
112
+
113
+ def remeasure value
114
+ Measurement.new(value, unit_name, exponent)
115
+ end
116
+
117
+ def library
118
+ Library.instance
119
+ end
120
+
88
121
  def ensure_shared_type! measurement
89
122
  if !has_shared_types?(measurement.unit_name)
90
123
  incompatible_types
@@ -100,7 +133,7 @@ module Alchemist
100
133
  end
101
134
 
102
135
  def conversion_base_for unit_type
103
- Alchemist.conversion_table[unit_type][unit_name]
136
+ library.conversion_base_for(unit_type, unit_name)
104
137
  end
105
138
 
106
139
  def has_shared_types? other_unit_name
@@ -109,7 +142,7 @@ module Alchemist
109
142
 
110
143
  def try_raising_dimension(measurement)
111
144
  valid_types = shared_types(measurement.unit_name)
112
- Alchemist.operator_actions[:*].each do |s1, s2, new_type|
145
+ library.operator_actions[:*].each do |s1, s2, new_type|
113
146
  if (valid_types & [s1, s2]).any?
114
147
  return Alchemist.measure(value * measurement.to_f, new_type)
115
148
  end
@@ -1,4 +1,5 @@
1
1
  require 'bigdecimal'
2
+ require 'alchemist/prefix_parser'
2
3
 
3
4
  module Alchemist
4
5
  class MeasurementConvertor
@@ -7,27 +8,42 @@ module Alchemist
7
8
  end
8
9
 
9
10
  def method_missing method, *args, &block
10
- exponent, unit_name = Alchemist.parse_prefix(method)
11
- convert(from.shared_types(unit_name), unit_name, exponent)
11
+ exponent, unit_name = PrefixParser.new.parse(method)
12
+ convert(from.shared_types(unit_name), unit_name, args.first || exponent)
12
13
  end
13
14
 
14
15
  private
15
16
  attr_reader :from
16
17
 
18
+ def library
19
+ Library.instance
20
+ end
21
+
17
22
  def convert types, unit_name, exponent
18
23
  if type = types[0]
19
- conversion_base = BigDecimal.new(from.base(type).to_s)
20
- conversion_factor = Alchemist.conversion_table[type][unit_name]
21
- if proc_based?(conversion_factor)
22
- Measurement.new(conversion_factor[1].call(conversion_base), unit_name, exponent)
23
- else
24
- Measurement.new(conversion_base / BigDecimal.new(conversion_factor.to_s), unit_name, exponent)
25
- end
24
+ convert_from_type(type, unit_name, exponent)
26
25
  else
27
26
  raise Exception, "Incompatible Types"
28
27
  end
29
28
  end
30
29
 
30
+ def convert_from_type(type, unit_name, exponent)
31
+ conversion_base = BigDecimal.new(from.base(type).to_s)
32
+ conversion_factor = library.conversion_base_for(type, unit_name)
33
+
34
+ value = value_from(conversion_base, conversion_factor)
35
+ Measurement.new(value / exponent, unit_name, exponent)
36
+ end
37
+
38
+ def value_from(base, factor)
39
+ if proc_based?(factor)
40
+ factor[1].call(base)
41
+ else
42
+ base / BigDecimal.new(factor.to_s)
43
+ end
44
+
45
+ end
46
+
31
47
  def proc_based? conversion_factor
32
48
  conversion_factor.is_a? Array
33
49
  end
@@ -21,12 +21,12 @@ module Alchemist
21
21
  end
22
22
 
23
23
  def unit_names
24
- Alchemist.conversion_table[category.to_sym].map { |values| values[0] }
24
+ Library.instance.unit_names(category)
25
25
  end
26
26
 
27
27
  def prefixes_with_value(name)
28
- if Alchemist.si_units.include?(name.to_s)
29
- Alchemist.unit_prefixes
28
+ if Library.instance.si_units.include?(name.to_s)
29
+ Library.instance.unit_prefixes
30
30
  else
31
31
  []
32
32
  end
@@ -0,0 +1,42 @@
1
+ module Alchemist
2
+ class PrefixParser
3
+ def parse(unit)
4
+ matches = unit.to_s.match(prefix_matcher)
5
+ prefix, parsed_unit = matches.captures
6
+
7
+ if prefix && library.si_units.include?(parsed_unit)
8
+ value = prefixed_value_for(prefix.to_sym, parsed_unit)
9
+ [value, parsed_unit.to_sym]
10
+ else
11
+ [1, unit]
12
+ end
13
+ end
14
+
15
+ def prefix_matcher
16
+ @prefix_matcher ||= generate_prefix_matcher
17
+ end
18
+
19
+ private
20
+
21
+ def library
22
+ Alchemist.library
23
+ end
24
+
25
+ def generate_prefix_matcher
26
+ prefix_keys = library.unit_prefixes.keys.map(&:to_s).sort{ |a,b| b.length <=> a.length }
27
+ %r{^(#{prefix_keys.join('|')})?(.+)}
28
+ end
29
+
30
+ def prefixed_value_for prefix, unit
31
+ if use_binary_prefix? unit
32
+ library.binary_prefixes[prefix]
33
+ else
34
+ library.unit_prefixes[prefix]
35
+ end
36
+ end
37
+
38
+ def use_binary_prefix? unit
39
+ !Alchemist.config.use_si? && library.measurement_for(unit).include?(:information_storage)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ require 'alchemist'
2
+
3
+ Alchemist.setup
@@ -1,3 +1,3 @@
1
1
  module Alchemist
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
@@ -3,14 +3,11 @@ require 'spec_helper'
3
3
  describe Alchemist do
4
4
 
5
5
  it "sets up Numeric" do
6
- category_module = double()
7
- module_builder = double()
8
- module_builder.should_receive(:build).and_return(category_module)
9
- fake_module = double()
10
- fake_module.should_receive(:include).with(category_module)
11
- Alchemist::ModuleBuilder.should_receive(:new).with('distance').and_return(module_builder)
12
- stub_const("Numeric", fake_module)
6
+ category_module = build_category_module
7
+ fake_numeric = build_fake_numeric
13
8
  Alchemist.setup('distance')
9
+ expect(Alchemist::ModuleBuilder).to have_received(:new).with('distance')
10
+ expect(fake_numeric).to have_received(:include).with(category_module)
14
11
  end
15
12
 
16
13
  it "creates a measurement" do
@@ -18,34 +15,18 @@ describe Alchemist do
18
15
  expect(unit).to eq(1.meter)
19
16
  end
20
17
 
21
- it "knows if it has a measurement" do
22
- expect(Alchemist.has_measurement?(:meter)).to be_true
18
+ def build_category_module
19
+ double.tap do |category_module|
20
+ module_builder = double()
21
+ allow(module_builder).to receive(:build) { category_module }
22
+ Alchemist::ModuleBuilder.stub(:new).and_return(module_builder)
23
+ end
23
24
  end
24
25
 
25
- it "knows if it doesn't have a measurement" do
26
- expect(Alchemist.has_measurement?(:wombat)).to be_false
27
- end
28
-
29
- it "can register units" do
30
- Alchemist.register :quux, :qaat, 1.0
31
- Alchemist.register :quux, :quut, 3.0
32
- expect(Alchemist.conversion_table[:quux]).to eq({:qaat=>1.0, :quut=>3.0})
33
- end
34
-
35
- it "can register units with plural names" do
36
- Alchemist.register(:beards, [:beard_second, :beard_seconds], 1.0)
37
- expect(Alchemist.conversion_table[:beards]).to eq({:beard_second=>1.0, :beard_seconds=>1.0})
38
- end
39
-
40
- it "can register units with formulas" do
41
- to = lambda { |t| t + 1 }
42
- from = lambda { |t| t - 1 }
43
- Alchemist.register(:yetis, :yeti, [to, from])
44
- expect(Alchemist.conversion_table[:yetis]).to eq({:yeti => [to, from]})
45
- end
46
-
47
- it "can parse a prefix" do
48
- parsed = Alchemist.parse_prefix(:kilometer)
49
- expect(parsed).to eq([1000.0, :meter])
26
+ def build_fake_numeric
27
+ double.tap do |fake_module|
28
+ allow(fake_module).to receive(:include)
29
+ stub_const("Numeric", fake_module)
30
+ end
50
31
  end
51
32
  end
@@ -17,11 +17,11 @@ module Alchemist
17
17
  end
18
18
 
19
19
  def conversion_table
20
- Alchemist::conversion_table
20
+ Alchemist.library.conversion_table
21
21
  end
22
22
 
23
23
  def load_file file
24
- Alchemist::load_conversion_table file
24
+ Alchemist.library.load_conversion_table file
25
25
  end
26
26
 
27
27
  def good_file
@@ -33,7 +33,7 @@ module Alchemist
33
33
  end
34
34
 
35
35
  def default_file
36
- File.join(File.dirname(__FILE__), "..", "lib", "alchemist", "units.yml")
36
+ Configuration::DEFAULT_UNITS_FILE
37
37
  end
38
38
  end
39
39
  end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ module Alchemist
4
+ describe Library do
5
+ it "returns a list of the binary prefixes" do
6
+ expect(library.binary_prefixes[:kilo]).to eq(1024.0)
7
+ end
8
+
9
+ it "can register units with formulas" do
10
+ to = lambda { |t| t + 1 }
11
+ from = lambda { |t| t - 1 }
12
+ library.register(:yetis, :yeti, [to, from])
13
+ expect(library.conversion_table[:yetis]).to eq({:yeti => [to, from]})
14
+ end
15
+
16
+ it "can register units with plural names" do
17
+ library.register(:beards, [:beard_second, :beard_seconds], 1.0)
18
+ expect(library.conversion_table[:beards]).to eq({:beard_second=>1.0, :beard_seconds=>1.0})
19
+ end
20
+
21
+ it "can register units" do
22
+ library.register :quux, :qaat, 1.0
23
+ library.register :quux, :quut, 3.0
24
+ expect(library.conversion_table[:quux]).to eq({:qaat=>1.0, :quut=>3.0})
25
+ end
26
+
27
+ it "knows if it has a measurement" do
28
+ expect(library.has_measurement?(:meter)).to be_true
29
+ end
30
+
31
+ it "knows if it doesn't have a measurement" do
32
+ expect(library.has_measurement?(:wombat)).to be_false
33
+ end
34
+
35
+ def library
36
+ Library.instance
37
+ end
38
+ end
39
+ end
@@ -15,12 +15,13 @@ module Alchemist
15
15
  end
16
16
 
17
17
  it "can be multiplied" do
18
- Alchemist.register_operation_conversions(:distance, :distance, :*, :square_meters)
18
+ Alchemist.library.register_operation_conversions(:distance, :distance, :*, :square_meters)
19
19
  expect(1.meter * 1.meter).to eq(1.square_meter)
20
20
  end
21
21
 
22
22
  it "can be divided" do
23
23
  expect(2.meters / 1.meter).to eq(2.0)
24
+ expect(4.meters / 2).to eq(2.meters)
24
25
  end
25
26
 
26
27
  it "can be added" do
@@ -55,6 +56,25 @@ module Alchemist
55
56
  expect(1.meter.coerce(10)).to eq([1.meter, 10])
56
57
  end
57
58
 
59
+ it "can round measurements" do
60
+ expect(1.5.meters.round).to eq(2.meters)
61
+ end
62
+
63
+ it "can ceil measurements" do
64
+ expect(1.4.meters.ceil).to eq(2.meters)
65
+ end
66
+
67
+ it "can floor measurments" do
68
+ expect(1.6.meters.floor).to eq(1.meter)
69
+ end
70
+
71
+ it "handles exponents correctly" do
72
+ expect(1.kg.to.kg).to eq(1.kg)
73
+ expect(1.kg.to(:kg)).to eq(1.kg)
74
+ expect(1.kg.to.kg.to.g).to eq(1000.g)
75
+ expect(1.kg.to.g.to.kg).to eq(1.kg)
76
+ end
77
+
58
78
  describe '#geospatial' do
59
79
 
60
80
  it 'should convert angles to meters' do
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ module Alchemist
4
+ describe PrefixParser do
5
+ it "can parse a prefix" do
6
+ parsed = PrefixParser.new.parse(:kilometer)
7
+ expect(parsed).to eq([1000.0, :meter])
8
+ end
9
+ end
10
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alchemist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Mongeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-02 00:00:00.000000000 Z
11
+ date: 2013-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -53,23 +53,29 @@ files:
53
53
  - alchemist.gemspec
54
54
  - lib/alchemist.rb
55
55
  - lib/alchemist/compound_measurement.rb
56
+ - lib/alchemist/configuration.rb
56
57
  - lib/alchemist/conversion_table.rb
57
58
  - lib/alchemist/data/binary_prefixes.yml
58
59
  - lib/alchemist/data/si_units.yml
59
60
  - lib/alchemist/data/unit_prefixes.yml
60
61
  - lib/alchemist/data/units.yml
61
62
  - lib/alchemist/geospatial.rb
63
+ - lib/alchemist/library.rb
62
64
  - lib/alchemist/measurement.rb
63
65
  - lib/alchemist/measurement_convertor.rb
64
66
  - lib/alchemist/module_builder.rb
65
67
  - lib/alchemist/objects/planets/earth.rb
68
+ - lib/alchemist/prefix_parser.rb
69
+ - lib/alchemist/setup.rb
66
70
  - lib/alchemist/version.rb
67
71
  - spec/alchemist_spec.rb
68
72
  - spec/compound_measurement_spec.rb
69
73
  - spec/conversion_table_spec.rb
70
74
  - spec/fixtures/bad_test.yml
71
75
  - spec/fixtures/good_test.yml
76
+ - spec/library_spec.rb
72
77
  - spec/measurement_spec.rb
78
+ - spec/prefix_parser_spec.rb
73
79
  - spec/spec_helper.rb
74
80
  homepage: http://github.com/halogenandtoast/alchemist
75
81
  licenses:
@@ -101,6 +107,8 @@ test_files:
101
107
  - spec/conversion_table_spec.rb
102
108
  - spec/fixtures/bad_test.yml
103
109
  - spec/fixtures/good_test.yml
110
+ - spec/library_spec.rb
104
111
  - spec/measurement_spec.rb
112
+ - spec/prefix_parser_spec.rb
105
113
  - spec/spec_helper.rb
106
114
  has_rdoc: