alchemist 0.1.7 → 0.1.8
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 +5 -5
- data/.gitignore +3 -0
- data/Gemfile.lock +10 -1
- data/NEWS.md +6 -0
- data/README.md +13 -6
- data/Rakefile +5 -0
- data/alchemist.gemspec +3 -2
- data/lib/alchemist.rb +39 -2
- data/lib/alchemist/compound_measurement.rb +17 -2
- data/lib/alchemist/configuration.rb +2 -8
- data/lib/alchemist/conversion_calculator.rb +47 -0
- data/lib/alchemist/library.rb +31 -8
- data/lib/alchemist/measurement.rb +37 -19
- data/lib/alchemist/measurement_convertor.rb +8 -28
- data/lib/alchemist/module_builder.rb +32 -22
- data/lib/alchemist/objects/planets/earth.rb +1 -1
- data/lib/alchemist/prefix_parser.rb +21 -16
- data/lib/alchemist/version.rb +1 -1
- data/spec/alchemist_spec.rb +63 -14
- data/spec/byte_spec.rb +14 -0
- data/spec/compound_measurement_spec.rb +16 -0
- data/spec/configuration_spec.rb +16 -0
- data/spec/conversion_table_spec.rb +6 -20
- data/spec/error_spec.rb +11 -0
- data/spec/library_spec.rb +18 -4
- data/spec/measurement_convertor_spec.rb +7 -0
- data/spec/measurement_spec.rb +13 -1
- data/spec/module_builder_spec.rb +16 -0
- data/spec/prefix_parser_spec.rb +14 -2
- data/spec/spec_helper.rb +13 -0
- metadata +38 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2d96474ca74ad168ff21a950de907b6f09974ba748c66457bd0f6528ac6aafde
|
4
|
+
data.tar.gz: 756514b42731f45ed578e872943bd2004cdf4ec0ede8feb2fcdf204a6ece2431
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f363df781906fb3e2defd4719adbeb90a285bedf7ad833233019697f11ce63caf96f31d80e5903433a4da32c009d79a1187457b7ff958319e23d3b3f87d7e60c
|
7
|
+
data.tar.gz: 2be97bbc13985330796ddebef1c611c495dd20fbb9885ee932b2930833578a046b71dcea47ccd3cd6bc1534b0fb57e3d65c76109ca6a35a77f12fed165e7852c
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
alchemist (0.1.
|
4
|
+
alchemist (0.1.8)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
diff-lcs (1.2.4)
|
10
|
+
multi_json (1.8.2)
|
10
11
|
rake (10.0.3)
|
11
12
|
rspec (2.14.1)
|
12
13
|
rspec-core (~> 2.14.0)
|
@@ -16,6 +17,10 @@ GEM
|
|
16
17
|
rspec-expectations (2.14.0)
|
17
18
|
diff-lcs (>= 1.1.3, < 2.0)
|
18
19
|
rspec-mocks (2.14.1)
|
20
|
+
simplecov (0.7.1)
|
21
|
+
multi_json (~> 1.0)
|
22
|
+
simplecov-html (~> 0.7.1)
|
23
|
+
simplecov-html (0.7.1)
|
19
24
|
|
20
25
|
PLATFORMS
|
21
26
|
ruby
|
@@ -24,3 +29,7 @@ DEPENDENCIES
|
|
24
29
|
alchemist!
|
25
30
|
rake
|
26
31
|
rspec
|
32
|
+
simplecov
|
33
|
+
|
34
|
+
BUNDLED WITH
|
35
|
+
2.0.2
|
data/NEWS.md
ADDED
data/README.md
CHANGED
@@ -10,19 +10,19 @@ code more readable.
|
|
10
10
|
Having code that looks like this is meaningless
|
11
11
|
|
12
12
|
```ruby
|
13
|
-
|
13
|
+
meters = 8 * 1609.344
|
14
14
|
```
|
15
15
|
|
16
16
|
You could add comments
|
17
17
|
|
18
18
|
```ruby
|
19
|
-
|
19
|
+
meters = 8 * 1609.344 # converting miles to meters
|
20
20
|
```
|
21
21
|
|
22
22
|
But why not have this!
|
23
23
|
|
24
24
|
```ruby
|
25
|
-
8.
|
25
|
+
8.miles.to.meters
|
26
26
|
```
|
27
27
|
|
28
28
|
You can even perform mathematical operations
|
@@ -47,7 +47,7 @@ require 'alchemist/geospatial'
|
|
47
47
|
To switch to the IEC memory standard, force SI units with
|
48
48
|
|
49
49
|
```ruby
|
50
|
-
Alchemist
|
50
|
+
Alchemist.config.use_si = true
|
51
51
|
```
|
52
52
|
|
53
53
|
To see all the units alchemist has built in conversion for, check out the [units file](lib/alchemist/data/units.yml)
|
@@ -78,8 +78,15 @@ if you only want to use one category for conversions you can load it individuall
|
|
78
78
|
Alchemist.setup('distance') # This will load only distance
|
79
79
|
```
|
80
80
|
|
81
|
-
Rails
|
82
|
-
|
81
|
+
Rails
|
82
|
+
-----
|
83
|
+
|
84
|
+
#### Setup
|
85
|
+
|
86
|
+
It is suggested that you add your `Alchemist.setup` call to `config/initializers/alchemist.rb` and then restart your rails server.
|
87
|
+
|
88
|
+
|
89
|
+
#### Rails Warning
|
83
90
|
|
84
91
|
Rails adds some methods like `bytes` to `Numeric` so it's highly recommended that instead of trying to call `bytes` on a numeric, you should use the `measure` method:
|
85
92
|
|
data/Rakefile
CHANGED
data/alchemist.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.authors = ["Matthew Mongeau"]
|
10
10
|
gem.email = ["halogenandtoast@gmail.com"]
|
11
11
|
gem.homepage = 'http://github.com/halogenandtoast/alchemist'
|
12
|
-
gem.summary = '
|
13
|
-
gem.description = '
|
12
|
+
gem.summary = 'A scientific conversion library'
|
13
|
+
gem.description = 'A scientific conversion library'
|
14
14
|
gem.license = 'MIT'
|
15
15
|
|
16
16
|
gem.files = `git ls-files`.split($/)
|
@@ -19,4 +19,5 @@ Gem::Specification.new do |gem|
|
|
19
19
|
|
20
20
|
gem.add_development_dependency 'rake'
|
21
21
|
gem.add_development_dependency 'rspec'
|
22
|
+
gem.add_development_dependency 'simplecov'
|
22
23
|
end
|
data/lib/alchemist.rb
CHANGED
@@ -4,19 +4,56 @@ require "alchemist/compound_measurement"
|
|
4
4
|
require "alchemist/module_builder"
|
5
5
|
require "alchemist/configuration"
|
6
6
|
require "alchemist/library"
|
7
|
+
require "alchemist/conversion_calculator"
|
7
8
|
|
8
9
|
module Alchemist
|
10
|
+
|
9
11
|
autoload :Earth, "alchemist/objects/planets/earth"
|
10
12
|
|
13
|
+
class IncompatibleTypeError < StandardError ; end
|
14
|
+
class GeospatialArgumentError < StandardError ; end
|
15
|
+
|
11
16
|
def self.setup category = nil
|
12
17
|
if category
|
13
|
-
|
18
|
+
load_category category
|
14
19
|
else
|
15
|
-
|
20
|
+
load_all_categories
|
16
21
|
end
|
17
22
|
end
|
18
23
|
|
19
24
|
def self.measure value, unit, exponent = 1.0
|
20
25
|
Measurement.new value, unit, exponent
|
21
26
|
end
|
27
|
+
|
28
|
+
def self.measure_prefixed value, prefix, unit
|
29
|
+
exponent = library.exponent_for(unit, prefix)
|
30
|
+
Measurement.new value, unit, exponent, prefix: prefix
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.library
|
34
|
+
@library ||= Library.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.config
|
38
|
+
@configuration ||= Configuration.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.register(types, names, value)
|
42
|
+
library.register(types, names, value)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.reset!
|
46
|
+
@library = nil
|
47
|
+
@configuration = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def self.load_all_categories
|
53
|
+
library.load_all_categories
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.load_category category
|
57
|
+
library.load_category(category)
|
58
|
+
end
|
22
59
|
end
|
@@ -1,13 +1,22 @@
|
|
1
1
|
module Alchemist
|
2
2
|
class CompoundMeasurement
|
3
|
+
include Comparable
|
3
4
|
attr_accessor :numerators, :denominators
|
4
5
|
|
5
6
|
def initialize(numerator)
|
6
|
-
@coefficient =
|
7
|
-
@numerators = [numerator]
|
7
|
+
@coefficient = numerator.value
|
8
|
+
@numerators = [numerator / @coefficient]
|
8
9
|
@denominators = []
|
9
10
|
end
|
10
11
|
|
12
|
+
def <=> other
|
13
|
+
if @coefficient == other.coefficient
|
14
|
+
[@numerators, @denominators] <=> [other.numerators, other.denominators]
|
15
|
+
else
|
16
|
+
@coefficient <=> other.coefficient
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
11
20
|
def *(value)
|
12
21
|
case value
|
13
22
|
when Numeric
|
@@ -19,6 +28,8 @@ module Alchemist
|
|
19
28
|
end
|
20
29
|
end
|
21
30
|
|
31
|
+
private
|
32
|
+
|
22
33
|
def consolidate
|
23
34
|
compress_units
|
24
35
|
set_coefficients
|
@@ -61,5 +72,9 @@ module Alchemist
|
|
61
72
|
consolidate
|
62
73
|
end
|
63
74
|
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
|
78
|
+
attr_reader :coefficient
|
64
79
|
end
|
65
80
|
end
|
@@ -1,20 +1,14 @@
|
|
1
|
-
require 'singleton'
|
2
|
-
|
3
1
|
module Alchemist
|
4
|
-
def self.config
|
5
|
-
Configuration.instance
|
6
|
-
end
|
7
|
-
|
8
2
|
class Configuration
|
3
|
+
|
9
4
|
DATA_DIR = File.join(File.dirname(__FILE__), "data")
|
10
5
|
DEFAULT_UNITS_FILE = File.join(DATA_DIR, "units.yml")
|
11
6
|
DEFAULT_SI_UNITS_FILE = File.join(DATA_DIR, "si_units.yml")
|
12
7
|
DEFAULT_BINARY_PREFIXES_FILE = File.join(DATA_DIR, "binary_prefixes.yml")
|
13
8
|
DEFAULT_UNIT_PREFIXES_FILE = File.join(DATA_DIR, "unit_prefixes.yml")
|
14
9
|
|
15
|
-
include Singleton
|
16
|
-
|
17
10
|
attr_accessor :use_si
|
11
|
+
|
18
12
|
def initialize
|
19
13
|
@use_si = false
|
20
14
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Alchemist
|
2
|
+
class ConversionCalculator
|
3
|
+
def initialize(from, parsed_unit)
|
4
|
+
@from = from
|
5
|
+
@parsed_unit = parsed_unit
|
6
|
+
end
|
7
|
+
|
8
|
+
def calculate
|
9
|
+
Measurement.new(value / exponent, unit_name, exponent)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
attr_reader :from, :parsed_unit
|
14
|
+
|
15
|
+
def exponent
|
16
|
+
parsed_unit.exponent
|
17
|
+
end
|
18
|
+
|
19
|
+
def unit_name
|
20
|
+
parsed_unit.unit_name
|
21
|
+
end
|
22
|
+
|
23
|
+
def value
|
24
|
+
if proc_based?
|
25
|
+
factor[1].call(base)
|
26
|
+
else
|
27
|
+
base / BigDecimal(factor.to_s)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def proc_based?
|
32
|
+
factor.is_a? Array
|
33
|
+
end
|
34
|
+
|
35
|
+
def base
|
36
|
+
@base ||= BigDecimal(from.base(type).to_s)
|
37
|
+
end
|
38
|
+
|
39
|
+
def type
|
40
|
+
@type ||= parsed_unit.guess_type(from)
|
41
|
+
end
|
42
|
+
|
43
|
+
def factor
|
44
|
+
@factor = Alchemist.library.conversion_base_for(type, unit_name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/alchemist/library.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
|
-
require 'singleton'
|
2
|
-
|
3
1
|
module Alchemist
|
4
|
-
def self.library
|
5
|
-
Library.instance
|
6
|
-
end
|
7
|
-
|
8
2
|
class Library
|
9
|
-
include Singleton
|
10
3
|
|
11
4
|
attr_reader :si_units, :unit_prefixes, :conversion_table, :binary_prefixes
|
12
5
|
|
@@ -15,14 +8,42 @@ module Alchemist
|
|
15
8
|
@si_units = YAML.load_file(Configuration::DEFAULT_SI_UNITS_FILE)
|
16
9
|
@unit_prefixes = YAML.load_file(Configuration::DEFAULT_UNIT_PREFIXES_FILE)
|
17
10
|
@binary_prefixes = YAML.load_file(Configuration::DEFAULT_BINARY_PREFIXES_FILE)
|
11
|
+
@loaded_modules = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def exponent_for(name, prefix)
|
15
|
+
if binary_unit?(name)
|
16
|
+
binary_prefixes[prefix]
|
17
|
+
else
|
18
|
+
unit_prefixes[prefix]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def binary_unit?(name)
|
23
|
+
using_binary? && measurement_for(name).include?(:information_storage)
|
24
|
+
end
|
25
|
+
|
26
|
+
def using_binary?
|
27
|
+
!Alchemist.config.use_si?
|
18
28
|
end
|
19
29
|
|
20
30
|
def categories
|
21
31
|
@conversion_table.keys
|
22
32
|
end
|
23
33
|
|
34
|
+
def load_category(category)
|
35
|
+
@loaded_modules[category] ||= ModuleBuilder.new(category)
|
36
|
+
Numeric.send :include, @loaded_modules[category]
|
37
|
+
end
|
38
|
+
|
39
|
+
def load_all_categories
|
40
|
+
categories.each do |category|
|
41
|
+
load_category category
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
24
45
|
def unit_names category
|
25
|
-
@conversion_table[category.to_sym].map
|
46
|
+
@conversion_table[category.to_sym].map(&:first)
|
26
47
|
end
|
27
48
|
|
28
49
|
def measurement_for unit_name
|
@@ -68,6 +89,8 @@ module Alchemist
|
|
68
89
|
conversions[name] << type
|
69
90
|
conversion_table[type][name] = value
|
70
91
|
end
|
92
|
+
|
93
|
+
@loaded_modules[type].define_unit_method(names)
|
71
94
|
end
|
72
95
|
|
73
96
|
private
|
@@ -1,15 +1,21 @@
|
|
1
|
+
require "bigdecimal"
|
1
2
|
require "alchemist/measurement_convertor"
|
2
3
|
|
3
4
|
module Alchemist
|
4
5
|
class Measurement
|
5
6
|
include Comparable
|
6
7
|
|
7
|
-
attr_reader :
|
8
|
+
attr_reader :unprefixed_unit_name, :exponent, :value, :prefix
|
8
9
|
|
9
|
-
def initialize value, unit_name, exponent = 1.0
|
10
|
+
def initialize value, unit_name, exponent = 1.0, options = {}
|
10
11
|
@value = value.to_f
|
11
|
-
@
|
12
|
+
@unprefixed_unit_name = unit_name.to_sym
|
12
13
|
@exponent = exponent
|
14
|
+
@prefix = options[:prefix] || ""
|
15
|
+
end
|
16
|
+
|
17
|
+
def unit_name
|
18
|
+
"#{prefix}#{unprefixed_unit_name}"
|
13
19
|
end
|
14
20
|
|
15
21
|
def per
|
@@ -27,13 +33,15 @@ module Alchemist
|
|
27
33
|
def + measurement
|
28
34
|
ensure_shared_type!(measurement)
|
29
35
|
converted = measurement.to(unit_name)
|
30
|
-
|
36
|
+
addend = converted.value / exponent
|
37
|
+
remeasure(value + addend)
|
31
38
|
end
|
32
39
|
|
33
40
|
def - measurement
|
34
41
|
ensure_shared_type!(measurement)
|
35
42
|
converted = measurement.to(unit_name)
|
36
|
-
|
43
|
+
subtrahend = converted.value / exponent
|
44
|
+
remeasure(value - subtrahend)
|
37
45
|
end
|
38
46
|
|
39
47
|
def / measurement
|
@@ -68,15 +76,19 @@ module Alchemist
|
|
68
76
|
end
|
69
77
|
|
70
78
|
def to_f
|
71
|
-
|
79
|
+
(precise_value * exponent).to_f
|
80
|
+
end
|
81
|
+
|
82
|
+
def <=> other
|
83
|
+
to_f <=> other.to(unit_name).to_f
|
72
84
|
end
|
73
85
|
|
74
|
-
def
|
75
|
-
|
86
|
+
def == other
|
87
|
+
to_f <=> other.to(unit_name).to_f
|
76
88
|
end
|
77
89
|
|
78
90
|
def types
|
79
|
-
library.measurement_for(
|
91
|
+
library.measurement_for(unprefixed_unit_name)
|
80
92
|
end
|
81
93
|
|
82
94
|
def shared_types other_unit_name
|
@@ -115,12 +127,12 @@ module Alchemist
|
|
115
127
|
end
|
116
128
|
|
117
129
|
def library
|
118
|
-
|
130
|
+
Alchemist.library
|
119
131
|
end
|
120
132
|
|
121
133
|
def ensure_shared_type! measurement
|
122
|
-
if !has_shared_types?(measurement.
|
123
|
-
|
134
|
+
if !has_shared_types?(measurement.unprefixed_unit_name)
|
135
|
+
incompatible_type_error
|
124
136
|
end
|
125
137
|
end
|
126
138
|
|
@@ -128,12 +140,12 @@ module Alchemist
|
|
128
140
|
if conversion_base.is_a?(Array)
|
129
141
|
exponent * conversion_base.first.call(value)
|
130
142
|
else
|
131
|
-
|
143
|
+
precise_value * conversion_base * exponent
|
132
144
|
end
|
133
145
|
end
|
134
146
|
|
135
147
|
def conversion_base_for unit_type
|
136
|
-
library.conversion_base_for(unit_type,
|
148
|
+
library.conversion_base_for(unit_type, unprefixed_unit_name)
|
137
149
|
end
|
138
150
|
|
139
151
|
def has_shared_types? other_unit_name
|
@@ -147,15 +159,21 @@ module Alchemist
|
|
147
159
|
return Alchemist.measure(value * measurement.to_f, new_type)
|
148
160
|
end
|
149
161
|
end
|
150
|
-
|
151
|
-
end
|
152
|
-
|
153
|
-
def incompatible_types
|
154
|
-
raise Exception, "Incompatible Types"
|
162
|
+
incompatible_type_error
|
155
163
|
end
|
156
164
|
|
157
165
|
def convertor
|
158
166
|
MeasurementConvertor.new(self)
|
159
167
|
end
|
168
|
+
|
169
|
+
def precise_value
|
170
|
+
BigDecimal(@value.to_s)
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def incompatible_type_error
|
176
|
+
raise IncompatibleTypeError, "Incompatible Types"
|
177
|
+
end
|
160
178
|
end
|
161
179
|
end
|
@@ -8,44 +8,24 @@ module Alchemist
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def method_missing method, *args, &block
|
11
|
-
|
12
|
-
convert(
|
11
|
+
parsed_unit = parse_prefix(method)
|
12
|
+
convert(parsed_unit)
|
13
13
|
end
|
14
14
|
|
15
15
|
private
|
16
16
|
attr_reader :from
|
17
17
|
|
18
|
-
def
|
19
|
-
|
18
|
+
def parse_prefix(name)
|
19
|
+
PrefixParser.new(name)
|
20
20
|
end
|
21
21
|
|
22
|
-
def convert types, unit_name, exponent
|
23
|
-
if type = types[0]
|
24
|
-
convert_from_type(type, unit_name, exponent)
|
25
|
-
else
|
26
|
-
raise Exception, "Incompatible Types"
|
27
|
-
end
|
28
|
-
end
|
29
22
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
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)
|
23
|
+
def convert parsed_unit
|
24
|
+
if parsed_unit.shares_type?(from)
|
25
|
+
ConversionCalculator.new(from, parsed_unit).calculate
|
41
26
|
else
|
42
|
-
|
27
|
+
raise IncompatibleTypeError, "Incompatible Types"
|
43
28
|
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
def proc_based? conversion_factor
|
48
|
-
conversion_factor.is_a? Array
|
49
29
|
end
|
50
30
|
end
|
51
31
|
end
|
@@ -1,41 +1,51 @@
|
|
1
1
|
module Alchemist
|
2
|
-
class ModuleBuilder
|
2
|
+
class ModuleBuilder < Module
|
3
3
|
def initialize category
|
4
|
-
|
4
|
+
define_inspect_method(category)
|
5
|
+
define_unit_methods(category)
|
5
6
|
end
|
6
7
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
category_module.class_eval category_methods
|
8
|
+
def define_unit_method(names)
|
9
|
+
names.each do |name|
|
10
|
+
define_method(name.to_sym) { Alchemist.measure self, name.to_sym }
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
private
|
15
|
-
attr_reader :category
|
16
15
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
end
|
16
|
+
def define_inspect_method(category)
|
17
|
+
define_method :inspect do
|
18
|
+
"#<Module(#{category})>"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def define_unit_methods(category)
|
23
|
+
unit_names(category).map do |name|
|
24
|
+
define_method name do
|
25
|
+
Alchemist.measure self, name.to_sym
|
26
|
+
end
|
27
|
+
prefixes_for(name).map do |prefix|
|
28
|
+
define_method "#{prefix}#{name}" do
|
29
|
+
Alchemist.measure_prefixed self, prefix.to_sym, name.to_sym
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
21
33
|
end
|
22
34
|
|
23
|
-
def
|
24
|
-
|
35
|
+
def library
|
36
|
+
Alchemist.library
|
25
37
|
end
|
26
38
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
39
|
+
def unit_names(category)
|
40
|
+
library.unit_names(category)
|
41
|
+
end
|
42
|
+
|
43
|
+
def prefixes_for(name)
|
44
|
+
if library.si_units.include?(name.to_s)
|
45
|
+
library.unit_prefixes.keys
|
30
46
|
else
|
31
47
|
[]
|
32
48
|
end
|
33
49
|
end
|
34
|
-
|
35
|
-
def prefixed_methods(name)
|
36
|
-
prefixes_with_value(name).map do |prefix, value|
|
37
|
-
%(define_method("#{prefix}#{name}") { Alchemist.measure self, :#{name}, #{value} })
|
38
|
-
end.join("\n")
|
39
|
-
end
|
40
50
|
end
|
41
51
|
end
|
@@ -1,14 +1,18 @@
|
|
1
1
|
module Alchemist
|
2
2
|
class PrefixParser
|
3
|
-
|
3
|
+
attr_reader :unit_name, :exponent
|
4
|
+
|
5
|
+
def initialize(unit)
|
6
|
+
@unit = unit
|
4
7
|
matches = unit.to_s.match(prefix_matcher)
|
5
8
|
prefix, parsed_unit = matches.captures
|
6
9
|
|
7
10
|
if prefix && library.si_units.include?(parsed_unit)
|
8
|
-
|
9
|
-
|
11
|
+
@exponent = library.exponent_for(parsed_unit, prefix.to_sym)
|
12
|
+
@unit_name = parsed_unit.to_sym
|
10
13
|
else
|
11
|
-
|
14
|
+
@exponent = 1
|
15
|
+
@unit_name = unit
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
@@ -16,8 +20,21 @@ module Alchemist
|
|
16
20
|
@prefix_matcher ||= generate_prefix_matcher
|
17
21
|
end
|
18
22
|
|
23
|
+
def shares_type?(from)
|
24
|
+
guess_type(from)
|
25
|
+
end
|
26
|
+
|
27
|
+
def guess_type(from)
|
28
|
+
shared_types(from).first
|
29
|
+
end
|
30
|
+
|
19
31
|
private
|
20
32
|
|
33
|
+
def shared_types from
|
34
|
+
library.measurement_for(from.unprefixed_unit_name) & library.measurement_for(unit_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
|
21
38
|
def library
|
22
39
|
Alchemist.library
|
23
40
|
end
|
@@ -26,17 +43,5 @@ module Alchemist
|
|
26
43
|
prefix_keys = library.unit_prefixes.keys.map(&:to_s).sort{ |a,b| b.length <=> a.length }
|
27
44
|
%r{^(#{prefix_keys.join('|')})?(.+)}
|
28
45
|
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
46
|
end
|
42
47
|
end
|
data/lib/alchemist/version.rb
CHANGED
data/spec/alchemist_spec.rb
CHANGED
@@ -1,32 +1,81 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Alchemist do
|
4
|
+
it "loads a single category into the library" do
|
5
|
+
library_double = stub_library
|
4
6
|
|
5
|
-
it "sets up Numeric" do
|
6
|
-
category_module = build_category_module
|
7
|
-
fake_numeric = build_fake_numeric
|
8
7
|
Alchemist.setup('distance')
|
9
|
-
|
10
|
-
expect(
|
8
|
+
|
9
|
+
expect(library_double).to have_received(:load_category).with('distance')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "loads all categories into the library" do
|
13
|
+
library_double = stub_library
|
14
|
+
|
15
|
+
Alchemist.setup
|
16
|
+
|
17
|
+
expect(library_double).to have_received(:load_all_categories)
|
11
18
|
end
|
12
19
|
|
13
20
|
it "creates a measurement" do
|
14
21
|
unit = Alchemist.measure(1, :meter)
|
22
|
+
|
15
23
|
expect(unit).to eq(1.meter)
|
16
24
|
end
|
17
25
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
26
|
+
it "delegates register to the Library" do
|
27
|
+
stub_library
|
28
|
+
|
29
|
+
Alchemist.register(:foo, :bar, :baz)
|
30
|
+
|
31
|
+
expect(Alchemist.library).to have_received(:register).with(:foo, :bar, :baz)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "builds a library" do
|
35
|
+
library_double = stub_library
|
36
|
+
|
37
|
+
expect(Alchemist.library).to eq library_double
|
38
|
+
end
|
39
|
+
|
40
|
+
it "builds its configuration" do
|
41
|
+
configuration_double = stub_configuration
|
42
|
+
|
43
|
+
expect(Alchemist.config).to eq configuration_double
|
44
|
+
end
|
45
|
+
|
46
|
+
it "will reset! the library" do
|
47
|
+
stub_library
|
48
|
+
2.times { Alchemist.library }
|
49
|
+
Alchemist.reset!
|
50
|
+
Alchemist.library
|
51
|
+
expect(Alchemist::Library).to have_received(:new).twice
|
52
|
+
end
|
53
|
+
|
54
|
+
it "will reset! the configuration" do
|
55
|
+
stub_configuration
|
56
|
+
2.times { Alchemist.config }
|
57
|
+
Alchemist.reset!
|
58
|
+
Alchemist.config
|
59
|
+
expect(Alchemist::Configuration).to have_received(:new).twice
|
60
|
+
end
|
61
|
+
|
62
|
+
def stub_library
|
63
|
+
double(Alchemist::Library, library_methods).tap do |library_double|
|
64
|
+
allow(Alchemist::Library).to receive(:new).and_return(library_double)
|
23
65
|
end
|
24
66
|
end
|
25
67
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
68
|
+
def library_methods
|
69
|
+
{
|
70
|
+
register: true,
|
71
|
+
load_category: true,
|
72
|
+
load_all_categories: true
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def stub_configuration
|
77
|
+
double(Alchemist::Configuration).tap do |configuration_double|
|
78
|
+
allow(Alchemist::Configuration).to receive(:new).and_return(configuration_double)
|
30
79
|
end
|
31
80
|
end
|
32
81
|
end
|
data/spec/byte_spec.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Alchemist
|
4
|
+
RSpec.describe "byte conversions" do
|
5
|
+
it "uses JEDEC specification" do
|
6
|
+
expect(1.kb.to.b.to_f).to eq(1024.0)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "uses SI when configured to do so" do
|
10
|
+
Alchemist.config.use_si = true
|
11
|
+
expect(1.kb.to.b.to_f).to eq(1000.0)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -9,5 +9,21 @@ module Alchemist
|
|
9
9
|
it "can handle elimination of a unit" do
|
10
10
|
expect(4.m.per.m).to eq(4)
|
11
11
|
end
|
12
|
+
|
13
|
+
it "can multiply a coefficient" do
|
14
|
+
expect(10.miles.per.second * 3).to eq(30.miles.per.second)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "considers units different by coefficient" do
|
18
|
+
expect(10.miles.per.second).not_to eq(30.miles.per.second)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "considers unit different by numerators" do
|
22
|
+
expect(10.miles.per.second).not_to eq(10.feet.per.second)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "considers unit different by denominators" do
|
26
|
+
expect(10.miles.per.second).not_to eq(10.miles.per.minutes)
|
27
|
+
end
|
12
28
|
end
|
13
29
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Alchemist
|
4
|
+
describe Configuration do
|
5
|
+
it "defaults use_si to false" do
|
6
|
+
config = Configuration.new
|
7
|
+
expect(config.use_si?).to be false
|
8
|
+
end
|
9
|
+
|
10
|
+
it "allows use_si to be changed" do
|
11
|
+
config = Configuration.new
|
12
|
+
config.use_si = true
|
13
|
+
expect(config.use_si?).to be true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -2,27 +2,17 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Alchemist
|
4
4
|
describe ConversionTable do
|
5
|
-
after(:each) do
|
6
|
-
load_file default_file
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should use the new file" do
|
10
|
-
load_file good_file
|
11
|
-
expect(conversion_table[:volume]).to eq({ litre: 1.0, swallow: 0.006, pint: 0.5506105 })
|
12
|
-
end
|
13
5
|
|
14
|
-
it "
|
15
|
-
|
16
|
-
expect(
|
6
|
+
it "loads a properly formed file" do
|
7
|
+
conversion_table = ConversionTable.new
|
8
|
+
expect(conversion_table.load_all(good_file)).not_to be_nil
|
17
9
|
end
|
18
10
|
|
19
|
-
|
20
|
-
|
11
|
+
it "fails to load a improperly formed file" do
|
12
|
+
conversion_table = ConversionTable.new
|
13
|
+
expect(conversion_table.load_all(bad_file)).to be_nil
|
21
14
|
end
|
22
15
|
|
23
|
-
def load_file file
|
24
|
-
Alchemist.library.load_conversion_table file
|
25
|
-
end
|
26
16
|
|
27
17
|
def good_file
|
28
18
|
File.join(File.dirname(__FILE__), "fixtures", "good_test.yml")
|
@@ -31,9 +21,5 @@ module Alchemist
|
|
31
21
|
def bad_file
|
32
22
|
File.join(File.dirname(__FILE__), "fixtures", "bad_test.yml")
|
33
23
|
end
|
34
|
-
|
35
|
-
def default_file
|
36
|
-
Configuration::DEFAULT_UNITS_FILE
|
37
|
-
end
|
38
24
|
end
|
39
25
|
end
|
data/spec/error_spec.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Alchemist, "errors" do
|
4
|
+
it "raises IncompatibleTypeError when invalid types are used" do
|
5
|
+
expect { 1.second + 1.meter }.to raise_error(Alchemist::IncompatibleTypeError)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "throws GeospatialArgumentError when invalid type is used" do
|
9
|
+
expect { 1.second.geospatial }.to raise_error(Alchemist::GeospatialArgumentError)
|
10
|
+
end
|
11
|
+
end
|
data/spec/library_spec.rb
CHANGED
@@ -3,10 +3,14 @@ require 'spec_helper'
|
|
3
3
|
module Alchemist
|
4
4
|
describe Library do
|
5
5
|
it "returns a list of the binary prefixes" do
|
6
|
+
library = Library.new
|
6
7
|
expect(library.binary_prefixes[:kilo]).to eq(1024.0)
|
7
8
|
end
|
8
9
|
|
9
10
|
it "can register units with formulas" do
|
11
|
+
stub_loading
|
12
|
+
library = Library.new
|
13
|
+
library.load_category :yetis
|
10
14
|
to = lambda { |t| t + 1 }
|
11
15
|
from = lambda { |t| t - 1 }
|
12
16
|
library.register(:yetis, :yeti, [to, from])
|
@@ -14,26 +18,36 @@ module Alchemist
|
|
14
18
|
end
|
15
19
|
|
16
20
|
it "can register units with plural names" do
|
21
|
+
stub_loading
|
22
|
+
library = Library.new
|
23
|
+
library.load_category :beards
|
17
24
|
library.register(:beards, [:beard_second, :beard_seconds], 1.0)
|
18
25
|
expect(library.conversion_table[:beards]).to eq({:beard_second=>1.0, :beard_seconds=>1.0})
|
19
26
|
end
|
20
27
|
|
21
28
|
it "can register units" do
|
29
|
+
stub_loading
|
30
|
+
library = Library.new
|
31
|
+
library.load_category :quux
|
22
32
|
library.register :quux, :qaat, 1.0
|
23
33
|
library.register :quux, :quut, 3.0
|
24
34
|
expect(library.conversion_table[:quux]).to eq({:qaat=>1.0, :quut=>3.0})
|
25
35
|
end
|
26
36
|
|
27
37
|
it "knows if it has a measurement" do
|
28
|
-
|
38
|
+
library = Library.new
|
39
|
+
expect(library.has_measurement?(:meter)).to be true
|
29
40
|
end
|
30
41
|
|
31
42
|
it "knows if it doesn't have a measurement" do
|
32
|
-
|
43
|
+
library = Library.new
|
44
|
+
expect(library.has_measurement?(:wombat)).to be false
|
33
45
|
end
|
34
46
|
|
35
|
-
def
|
36
|
-
|
47
|
+
def stub_loading
|
48
|
+
module_double = double(Module, define_unit_method: true)
|
49
|
+
allow(ModuleBuilder).to receive(:new).and_return(module_double)
|
50
|
+
allow(Numeric).to receive(:send).with(:include, module_double).and_return(true)
|
37
51
|
end
|
38
52
|
end
|
39
53
|
end
|
data/spec/measurement_spec.rb
CHANGED
@@ -6,6 +6,10 @@ module Alchemist
|
|
6
6
|
expect(1.m).to eq(1.meter)
|
7
7
|
end
|
8
8
|
|
9
|
+
it "has a unit name" do
|
10
|
+
expect(1.kilometer.unit_name).to eq("kilometer")
|
11
|
+
end
|
12
|
+
|
9
13
|
it "can be converted" do
|
10
14
|
expect(5.grams).to eq(0.005.kilograms)
|
11
15
|
end
|
@@ -32,6 +36,10 @@ module Alchemist
|
|
32
36
|
expect(5.meters + 2.inches).to eq(5.0508.meters)
|
33
37
|
end
|
34
38
|
|
39
|
+
it "can add different measurements with exponents" do
|
40
|
+
expect(10.kilometers + 1.mile).to eq(11.609344.kilometers)
|
41
|
+
end
|
42
|
+
|
35
43
|
it "can be subtracted" do
|
36
44
|
expect(3.meters - 2.meters).to eq(1.meter)
|
37
45
|
end
|
@@ -40,6 +48,10 @@ module Alchemist
|
|
40
48
|
expect(5.meters - 2.inches).to eq(4.9492.meters)
|
41
49
|
end
|
42
50
|
|
51
|
+
it "can subtract measurements with exponents" do
|
52
|
+
expect(10.kilometers - 1.mile).to eq(8.390656.kilometers)
|
53
|
+
end
|
54
|
+
|
43
55
|
it "can provide an integer value" do
|
44
56
|
expect(10.meters.to_i).to eq(10)
|
45
57
|
end
|
@@ -78,7 +90,7 @@ module Alchemist
|
|
78
90
|
describe '#geospatial' do
|
79
91
|
|
80
92
|
it 'should convert angles to meters' do
|
81
|
-
expect(1.degree.geospatial).to eq(111318.
|
93
|
+
expect(1.degree.geospatial).to eq(111318.84502145035.meters)
|
82
94
|
end
|
83
95
|
|
84
96
|
it 'should convert distances to radians' do
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Alchemist
|
4
|
+
describe ModuleBuilder do
|
5
|
+
it "allows methods to be added to the build module" do
|
6
|
+
allow(Alchemist).to receive(:library).and_return(library_double)
|
7
|
+
builder = ModuleBuilder.new(:test)
|
8
|
+
builder.define_unit_method([:wombat])
|
9
|
+
expect(builder.instance_methods).to include(:wombat)
|
10
|
+
end
|
11
|
+
|
12
|
+
def library_double
|
13
|
+
double(Alchemist::Library, unit_names: [], si_units: [])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/prefix_parser_spec.rb
CHANGED
@@ -3,8 +3,20 @@ require 'spec_helper'
|
|
3
3
|
module Alchemist
|
4
4
|
describe PrefixParser do
|
5
5
|
it "can parse a prefix" do
|
6
|
-
parsed = PrefixParser.new
|
7
|
-
expect(parsed).to eq(
|
6
|
+
parsed = PrefixParser.new(:kilometer)
|
7
|
+
expect(parsed.exponent).to eq(1000.0)
|
8
|
+
expect(parsed.unit_name).to eq(:meter)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "can parse binary prefixes if si is off" do
|
12
|
+
parsed = PrefixParser.new(:gigabyte)
|
13
|
+
expect(parsed.exponent).to eq(1024 ** 3)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "can parse si prefixes if si is on" do
|
17
|
+
Alchemist.config.use_si = true
|
18
|
+
parsed = PrefixParser.new(:gigabyte)
|
19
|
+
expect(parsed.exponent).to eq(1000 ** 3)
|
8
20
|
end
|
9
21
|
end
|
10
22
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
2
|
|
3
|
+
if ENV["COVERAGE"]
|
4
|
+
require 'simplecov'
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter "/spec/"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
3
10
|
require 'alchemist'
|
4
11
|
require 'alchemist/geospatial'
|
5
12
|
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.before(:each) do
|
15
|
+
Alchemist.reset!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
6
19
|
Alchemist.setup
|
metadata
CHANGED
@@ -1,59 +1,75 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alchemist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Mongeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: simplecov
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A scientific conversion library
|
42
56
|
email:
|
43
57
|
- halogenandtoast@gmail.com
|
44
58
|
executables: []
|
45
59
|
extensions: []
|
46
60
|
extra_rdoc_files: []
|
47
61
|
files:
|
48
|
-
- .gitignore
|
62
|
+
- ".gitignore"
|
49
63
|
- Gemfile
|
50
64
|
- Gemfile.lock
|
65
|
+
- NEWS.md
|
51
66
|
- README.md
|
52
67
|
- Rakefile
|
53
68
|
- alchemist.gemspec
|
54
69
|
- lib/alchemist.rb
|
55
70
|
- lib/alchemist/compound_measurement.rb
|
56
71
|
- lib/alchemist/configuration.rb
|
72
|
+
- lib/alchemist/conversion_calculator.rb
|
57
73
|
- lib/alchemist/conversion_table.rb
|
58
74
|
- lib/alchemist/data/binary_prefixes.yml
|
59
75
|
- lib/alchemist/data/si_units.yml
|
@@ -69,12 +85,17 @@ files:
|
|
69
85
|
- lib/alchemist/setup.rb
|
70
86
|
- lib/alchemist/version.rb
|
71
87
|
- spec/alchemist_spec.rb
|
88
|
+
- spec/byte_spec.rb
|
72
89
|
- spec/compound_measurement_spec.rb
|
90
|
+
- spec/configuration_spec.rb
|
73
91
|
- spec/conversion_table_spec.rb
|
92
|
+
- spec/error_spec.rb
|
74
93
|
- spec/fixtures/bad_test.yml
|
75
94
|
- spec/fixtures/good_test.yml
|
76
95
|
- spec/library_spec.rb
|
96
|
+
- spec/measurement_convertor_spec.rb
|
77
97
|
- spec/measurement_spec.rb
|
98
|
+
- spec/module_builder_spec.rb
|
78
99
|
- spec/prefix_parser_spec.rb
|
79
100
|
- spec/spec_helper.rb
|
80
101
|
homepage: http://github.com/halogenandtoast/alchemist
|
@@ -87,28 +108,32 @@ require_paths:
|
|
87
108
|
- lib
|
88
109
|
required_ruby_version: !ruby/object:Gem::Requirement
|
89
110
|
requirements:
|
90
|
-
- -
|
111
|
+
- - ">="
|
91
112
|
- !ruby/object:Gem::Version
|
92
113
|
version: '0'
|
93
114
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
115
|
requirements:
|
95
|
-
- -
|
116
|
+
- - ">="
|
96
117
|
- !ruby/object:Gem::Version
|
97
118
|
version: '0'
|
98
119
|
requirements: []
|
99
120
|
rubyforge_project:
|
100
|
-
rubygems_version: 2.
|
121
|
+
rubygems_version: 2.7.6
|
101
122
|
signing_key:
|
102
123
|
specification_version: 4
|
103
|
-
summary:
|
124
|
+
summary: A scientific conversion library
|
104
125
|
test_files:
|
105
126
|
- spec/alchemist_spec.rb
|
127
|
+
- spec/byte_spec.rb
|
106
128
|
- spec/compound_measurement_spec.rb
|
129
|
+
- spec/configuration_spec.rb
|
107
130
|
- spec/conversion_table_spec.rb
|
131
|
+
- spec/error_spec.rb
|
108
132
|
- spec/fixtures/bad_test.yml
|
109
133
|
- spec/fixtures/good_test.yml
|
110
134
|
- spec/library_spec.rb
|
135
|
+
- spec/measurement_convertor_spec.rb
|
111
136
|
- spec/measurement_spec.rb
|
137
|
+
- spec/module_builder_spec.rb
|
112
138
|
- spec/prefix_parser_spec.rb
|
113
139
|
- spec/spec_helper.rb
|
114
|
-
has_rdoc:
|