metamorphosis 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ The MIT LICENSE
2
+
3
+ Copyright (c) 2012 Wegowise, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ Metamorphosis
2
+ =============
3
+ An engine for allowing numeric values to convert between units.
4
+
5
+ [![Build Status](https://secure.travis-ci.org/wegowise/metamorphosis.png)](http://travis-ci.org/wegowise/metamorphosis)
6
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/wegowise/metamorphosis)
7
+
8
+ Usage
9
+ ==============
10
+
11
+ Add 'metamorphosis' to your Gemfile,
12
+
13
+ Bundle install
14
+
15
+ Inside your intializer use the predefined units:
16
+
17
+ ````
18
+ Metamorphosis.register_predefined_units
19
+ ````
20
+
21
+ or register your own:
22
+ ````
23
+ Metamorphosis.engine.register_unit(:wegowise, :british_thermal_units, 1)
24
+ Metamorphosis.engine.register_unit(:wegowise, :therms, 100_000)
25
+ ````
26
+
27
+ Once you've defined your units you now have freedom to make your values
28
+ more expressive:
29
+ ````
30
+ value = 200_000.british_thermal_units #200000.0 british_thermal_units
31
+ value = value.to.therms
32
+ value == 2.therms #true
33
+
34
+ ````
@@ -0,0 +1,8 @@
1
+ module Metamorphosis
2
+ end
3
+
4
+ project_root = File.dirname(__FILE__)
5
+ Dir.glob(project_root + '/metamorphosis/**/*.rb') {|file| require file}
6
+
7
+ require 'set'
8
+ require 'numeric'
@@ -0,0 +1,341 @@
1
+ module Metamorphosis
2
+ SI_UNITS = %w{m meter metre meters metres liter litre litres liters l L
3
+ farad farads F coulombs C gray grays Gy siemen siemens S
4
+ mhos mho ohm ohms volt volts V joule joules J newton newtons N
5
+ lux lx henry henrys H b B bits bytes bit byte lumen lumens lm
6
+ candela candelas cd tesla teslas T gauss Gs G gram gramme grams
7
+ grammes g watt watts W pascal pascals Pa becquerel becquerels
8
+ Bq curie curies Ci}.map(&:to_sym)
9
+
10
+ DEFAULT_PREFIXES = {
11
+ :googol => 1e+100,
12
+ :yotta => 1e+24, :Y => 1e+24,
13
+ :zetta => 1e+21, :Z => 1e+21,
14
+ :exa => 1e+18, :E => 1e+18,
15
+ :peta => 1e+15, :P => 1e+15,
16
+ :tera => 1e+12, :T => 1e+12,
17
+ :giga => 1e+9, :G => 1e+9,
18
+ :mega => 1e+6, :M => 1e+6,
19
+ :kilo => 1e+3, :k => 1e+3,
20
+ :hecto => 1e+2, :h => 1e+2,
21
+ :deca => 10, :da => 10,
22
+ :deci => 1e-1, :d => 1e-1,
23
+ :centi => 1e-2, :c => 1e-2,
24
+ :milli => 1e-3, :m => 1e-3,
25
+ :micro => 1e-6, :u => 1e-6,
26
+ :nano => 1e-9, :n => 1e-9,
27
+ :pico => 1e-12, :p => 1e-12,
28
+ :femto => 1e-15, :f => 1e-15,
29
+ :atto => 1e-18, :a => 1e-18,
30
+ :zepto => 1e-21, :z => 1e-21,
31
+ :yocto => 1e-24, :y => 1e-24,
32
+
33
+ # binary prefixes
34
+
35
+ :kibi => 2.0**10.0, :Ki => 2.0**10.0,
36
+ :mebi => 2.0**20.0, :Mi => 2.0**20.0,
37
+ :gibi => 2.0**30.0, :Gi => 2.0**30.0,
38
+ :tebi => 2.0**40.0, :Ti => 2.0**40.0,
39
+ :pebi => 2.0**50.0, :Pi => 2.0**50.0,
40
+ :exbi => 2.0**60.0, :Ei => 2.0**60.0,
41
+ :zebi => 2.0**70.0, :Zi => 2.0**70.0,
42
+ :yobi => 2.0**80.0, :Yi => 2.0**80.0
43
+ }
44
+
45
+ PRE_DEFINED_UNITS =
46
+ {
47
+ :absorbed_radiation_dose => {
48
+ :gray => 1.0, :grays => 1.0, :Gy => 1.0,
49
+ :rad => 1.0e-2, :rads => 1.0e-2
50
+ },
51
+ :angles => {
52
+ :radian => 1.0, :radians => 1.0,
53
+ :degree => Math::PI / 180.0, :degrees => Math::PI / 180.0,
54
+ :arcminute => Math::PI / 10800.0, :arcminutes => Math::PI / 10800.0,
55
+ :arcsecond => Math::PI / 648000.0, :arcseconds => Math::PI / 648000.0,
56
+ :mil => 9.817477e-4, :mils => 9.817477e-4,
57
+ :revolution => Math::PI * 2.0, :revolutions => Math::PI * 2.0,
58
+ :circle => Math::PI * 2.0, :circles => Math::PI * 2.0,
59
+ :right_angle => Math::PI / 2.0, :right_angles => Math::PI / 2.0,
60
+ :grad => Math::PI / 200.0, :grade => Math::PI / 200.0, :gradian => Math::PI / 200.0, :gon => Math::PI / 200.0, :grads => Math::PI / 200.0, :grades => Math::PI / 200.0, :gradians => Math::PI / 200.0, :gons => Math::PI / 200.0,
61
+ #unusual measurements
62
+ :furman => 9.58737992858887e-5, :furmans => 9.58737992858887e-5
63
+ },
64
+ :area => {
65
+ :square_meter => 1.0, :square_meters => 1.0, :square_metre => 1.0, :square_metres => 1.0,
66
+ :acre => 4046.85642, :acres => 4046.85642,
67
+ :are => 1.0e+2, :ares => 1.0e+2, :a => 1.0e+2,
68
+ :barn => 1.0e-28, :barns => 1.0e-28, :b => 1.0e-28,
69
+ :circular_mil => 5.067075e-10, :circular_mils => 5.067075e-10,
70
+ :hectare => 1.0e+4, :hectares => 1.0e+4, :ha => 1.0e+4,
71
+ :square_foot => 9.290304e-2, :square_feet => 9.290304e-2,
72
+ :square_inch => 6.4516e-4, :square_inches => 6.4516e-4,
73
+ :square_mile => 2.589988e+6, :square_miles => 2.589988e+6,
74
+ :square_yard => 0.83612736, :square_yards => 0.83612736
75
+ },
76
+ :capacitance => {
77
+ :farad => 1.0, :farads => 1.0, :F => 1.0,
78
+ :abfarad => 1.0e+9, :emu_of_capacitance => 1.0e+9, :abfarads => 1.0e+9, :emus_of_capacitance => 1.0e+9,
79
+ :statfarad => 1.112650e-12, :esu_of_capacitance => 1.112650e-12, :statfarads => 1.112650e-12, :esus_of_capacitance => 1.112650e-12
80
+ },
81
+ :density => {
82
+ :specific_gravity => 1, :sg => 1,
83
+ :brix => [Proc.new{ |d| -261.3 / (d - 261.3) }, Proc.new{ |d| 261.3 - (261.3 / d) }],
84
+ :plato => [Proc.new{ |d| -260.0 / (d - 260.0) }, Proc.new{ |d| 260.0 - (260.0 / d) }],
85
+ :baume => [Proc.new{ |d| -145.0 / (d - 145.0) }, Proc.new{ |d| 145.0 - (145.0 / d) }]
86
+ },
87
+ :distance => {
88
+ :meter => 1.0, :metres => 1.0, :meters => 1.0, :m => 1.0,
89
+ :fermi => 1.0e-15, :fermis => 1.0e-15,
90
+ :micron => 1.0e-6, :microns => 1.0e-6,
91
+ :chain => 20.1168, :chains => 20.1168,
92
+ :inch => 25.4e-3, :inches => 25.4e-3, :in => 25.4e-3,
93
+ :microinch => 2.54e-8, :microinches => 2.54e-8,
94
+ :mil => 2.54e-05, :mils => 2.54e-05,
95
+ :rod => 5.029210, :rods => 5.029210,
96
+ :league => 5556, :leagues => 5556,
97
+ :foot => 0.3048, :feet => 0.3048, :ft => 0.3048,
98
+ :yard => 0.9144, :yards => 0.9144, :yd => 0.9144,
99
+ :mile =>1609.344, :miles =>1609.344, :mi => 1609.344,
100
+ :astronomical_unit => 149.60e+9, :astronomical_units => 149.60e+9, :au => 149.60e+9, :ua => 149.60e+9,
101
+ :light_year => 9.461e+15, :light_years => 9.461e+15, :ly => 9.461e+15,
102
+ :parsec => 30.857e+15, :parsecs => 30.857e+15,
103
+ :nautical_mile => 1852.0, :nautical_miles => 1852.0,
104
+ :admirality_mile => 185.3184, :admirality_miles => 185.3184,
105
+ :fathom => 1.8288, :fathoms => 1.8288,
106
+ :cable_length => 185.2, :cable_lengths => 185.2,
107
+ :angstrom => 100.0e-12, :angstroms => 100.0e-12,
108
+ :pica => 4.233333e-3, :picas => 4.233333e-3,
109
+ :printer_pica => 4.217518e-3, :printer_picas => 4.217518e-3,
110
+ :point => 3.527778e-4, :points => 3.527778e-4,
111
+ :printer_point => 3.514598e-4, :printer_points => 3.514598e-4,
112
+ # unusual mesaurements
113
+ :empire_state_building => 449.0, :empire_state_buildings => 449.0,
114
+ :sears_tower => 519.0, :sears_towers => 519.0,
115
+ :seattle_space_needle => 184.0, :seattle_space_needles => 184.0, :space_needle => 184.0, :space_needles => 184.0,
116
+ :statue_of_liberty => 46.0, :statue_of_liberties => 46.0,
117
+ :washington_monument => 169.294, :washington_monuments => 169.294,
118
+ :eiffel_tower => 324.0, :eiffel_towers => 324.0,
119
+ :nelsons_column => 61.5, :nelsons_columns => 61.5,
120
+ :blackpool_tower => 158.0, :blackpool_towers => 158.0,
121
+ :big_ben => 96.3, :big_bens => 96.3, :clock_tower_of_the_palace_of_westminster => 96.3, :clock_towers_of_the_palace_of_westminster => 96.3,
122
+ :st_pauls_cathedral => 108.0, :st_pauls_cathedrals => 108.0,
123
+ :toronto_cn_tower => 553.0, :toronto_cn_towers => 553.0, :cn_tower => 553.0, :cn_towers => 553.0,
124
+ :circle_of_the_earth => 40075016.686, :equator => 40075016.686, :circles_of_the_earth => 40075016.686, :equators => 40075016.686,
125
+ :siriometer => 1.494838e+17, :siriometers => 1.494838e+17,
126
+ :football_field => 91.0, :football_fields => 91.0,
127
+ :length_of_a_double_decker_bus => 8.4, :height_of_a_double_decker_bus => 4.4,
128
+ :smoot => 1.7018, :smoots => 1.7018
129
+ },
130
+ :dose_equivalent => {
131
+ :sievert => 1.0, :sieverts => 1.0, :Si => 1.0,
132
+ :rem => 1.0e-2, :rems => 1.0e-2
133
+ },
134
+ :electric_charge => {
135
+ :coulomb => 1.0, :coulombs => 1.0, :C => 1.0,
136
+ :abcoulomb => 10.0, :abcoulombs => 10.0,
137
+ :ampere_hour => 3.6e+3, :ampere_hours => 3.6e+3,
138
+ :faraday => 9.648534e+4, :faradays => 9.648534e+4,
139
+ :franklin => 3.335641e-10, :franklins => 3.335641e-10, :Fr => 3.335641e-10,
140
+ :statcoulomb => 3.335641e-10, :statcoulombs => 3.335641e-10
141
+ },
142
+ :electric_conductance => {
143
+ :siemen => 1.0, :siemens => 1.0, :S => 1.0, :mho => 1.0,
144
+ :abmho => 1.0e+9, :absiemen => 1.0e+9, :absiemens => 1.0e+9,
145
+ :statmho => 1.112650e-12, :statsiemen => 1.112650e-12, :statsiemens => 1.112650e-12
146
+ },
147
+ :electrical_impedance => {
148
+ :ohm => 1.0, :ohms => 1.0,
149
+ :abohm => 1.0e-9, :emu_of_resistance => 1.0e-9, :abohms => 1.0e-9, :emus_of_resistance => 1.0e-9,
150
+ :statohm => 8.987552e+11, :esu_of_resistance => 8.987552e+11, :statohms => 8.987552e+11, :esus_of_resistance => 8.987552e+11
151
+ },
152
+ :electromotive_force => {
153
+ :volt => 1.0, :volts => 1.0, :V => 1.0,
154
+ :abvolt => 1.0e-8, :emu_of_electric_potential => 1.0e-8, :abvolts => 1.0e-8, :emus_of_electric_potential => 1.0e-8,
155
+ :statvolt => 2.997925e+2, :esu_of_electric_potential => 2.997925e+2, :statvolts => 2.997925e+2, :esus_of_electric_potential => 2.997925e+2
156
+ },
157
+ :energy => {
158
+ :joule => 1.0, :joules => 1.0, :J => 1.0, :watt_second => 1.0, :watt_seconds => 1.0,
159
+ :watt_hour => 3.6e+3, :watt_hours => 3.6e+3,
160
+ :ton_of_tnt => 4.184e+9, :tons_of_tnt => 4.184e+9,
161
+ :therm => 1.05506e+8, :therms => 1.05506e+8,
162
+ :us_therm => 1.054804e+8, :us_therms => 1.054804e+8,
163
+ :kilowatt_hour => 3.6e+6, :kilowatt_hours => 3.6e+6,
164
+ :kilocalorie => 4184.0, :kilocalories => 4184.0,
165
+ :calorie => 4.184, :calories => 4.184,
166
+ :mean_kilocalorie => 4190, :mean_kilocalories => 4190,
167
+ :mean_calorie => 4.190, :mean_calories => 4.190,
168
+ :it_kilocalorie => 4186.8, :it_kilocalories => 4186.8,
169
+ :it_calorie => 4.1868, :it_calories => 4.1868,
170
+ :foot_poundal => 4.214011e-2, :foot_poundals => 4.214011e-2,
171
+ :foot_pound_force => 1.355818,
172
+ :erg => 1.0e-7, :ergs => 1.0e-7,
173
+ :electronvolt => 1.602176e-19, :electronvolts => 1.602176e-19, :eV => 1.602176e-19,
174
+ :british_thermal_unit => 1.054350e+3, :british_thermal_units => 1.054350e+3,
175
+ :mean_british_thermal_unit => 1.05587e+3, :mean_british_thermal_units => 1.05587e+3,
176
+ :it_british_thermal_unit => 1.055056e+3, :it_british_thermal_units => 1.055056e+3,
177
+ #unusual measurements
178
+ :foe => 1e+44, :foes => 1e+44
179
+ },
180
+ :frequency => {
181
+ :hertz => 1.0, :hz => 1.0, :'Hz' => 1.0,
182
+ :revolutions_per_minute => 1/60.0, :rpm => 1/60.0,
183
+ :beats_per_minute => 1/60.0, :bpm => 1/60.0
184
+ },
185
+ :force => {
186
+ :newton => 1.0, :newtons => 1.0, :N => 1.0,
187
+ :dyne => 1.0e-5, :dynes => 1.0e-5, :dyn => 1.0e-5,
188
+ :kilogram_force => 9.80665, :kgf => 9.80665, :kilopond => 9.80665, :kiloponds => 9.80665, :kp => 9.80665,
189
+ :kip => 4.448222e+3, :kips => 4.448222e+3,
190
+ :ounce_force => 2.780139e-1, :ozf => 2.780139e-1,
191
+ :poundal => 1.382550e-1, :poundals => 1.382550e-1,
192
+ :pound_force => 4.448222, :lbf => 4.448222,
193
+ :ton_force => 8.896443e+3
194
+ },
195
+ :illuminance => {
196
+ :lux => 1.0, :lx => 1.0, :lumens_per_square_metre => 1.0, :lumens_per_square_meter => 1.0, :lumen_per_square_metre => 1.0, :lumen_per_square_meter => 1.0,
197
+ :phot => 1.0e+4, :phots => 1.0e+4, :ph => 1.0e+4,
198
+ :lumens_per_square_foot => 10.76391, :footcandle => 10.76391, :lumen_per_square_foot => 10.76391, :footcandles => 10.76391
199
+ },
200
+ :inductance => {
201
+ :henry => 1.0, :henrys => 1.0, :H => 1.0,
202
+ :abhenrys => 1.0e-9, :emus_of_inductance => 1.0e-9, :abhenry => 1.0e-9, :emu_of_inductance => 1.0e-9,
203
+ :stathenrys => 8.987552e+11, :esus_of_inductance => 8.987552e+11, :stathenry => 8.987552e+11, :esu_of_inductance => 8.987552e+11
204
+ },
205
+ :information_storage => {
206
+ :bit => 1.0, :bits => 1.0, :b => 1.0,
207
+ :byte => 8.0, :bytes => 8.0, :B => 8.0,
208
+ :nibbles => 4.0, :nybbles => 4.0
209
+ },
210
+ :luminous_flux => {
211
+ :lumen => 1.0, :lumens => 1.0, :lm => 1.0
212
+ },
213
+ :luminous_intensity => {
214
+ :candela => 1.0, :candelas => 1.0, :cd => 1.0
215
+ },
216
+ :magnetic_flux => {
217
+ :webers => 1.0, :Wb => 1.0,
218
+ :maxwells => 1.0e-8, :Mx => 1.0e-8,
219
+ :unit_poles => 1.256637e-7
220
+ },
221
+ :magnetic_inductance => {
222
+ :tesla => 1.0, :teslas => 1.0, :T => 1.0,
223
+ :gamma => 1.0e-9, :gammas => 1.0e-9,
224
+ :gauss => 1.0e-4, :Gs => 1.0e-4, :G => 1.0e-4
225
+ },
226
+ :mass => {
227
+ :gram => 1.0, :gramme => 1.0, :grams => 1.0, :grammes => 1.0, :g => 1.0,
228
+ :carat => 2.0e-1, :carats => 2.0e-1,
229
+ :ounce => 2.834952e+1, :ounces => 2.834952e+1, :oz => 2.834952e+1,
230
+ :pennyweight => 1.555174, :pennyweights => 1.555174, :dwt => 1.555174,
231
+ :pound => 453.59237, :pounds => 453.59237, :lb => 453.59237, :lbs => 453.59237,
232
+ :troy_pound => 373.2417, :apothecary_pound => 373.2417, :troy_pounds => 373.2417, :apothecary_pounds => 373.2417,
233
+ :slug => 14593.9029, :slugs => 14593.9029,
234
+ :assay_ton => 29.1667, :assay_tons => 29.1667, :AT => 29.1667,
235
+ :metric_ton => 1000000, :metric_tons => 1000000,
236
+ :ton => 907184.74, :tons => 907184.74, :short_tons => 907184.74,
237
+ #unusual measurements
238
+ :elephant => 5443108.44, :elephants => 5443108.44
239
+ },
240
+ :power => {
241
+ :watt => 1.0, :watts => 1.0, :W => 1.0,
242
+ :british_thermal_unit_per_hour => 2.928751e-1, :british_thermal_units_per_hour => 2.928751e-1,
243
+ :it_british_thermal_unit_per_hour => 2.930711e-1, :it_british_thermal_units_per_hour => 2.930711e-1,
244
+ :british_thermal_unit_per_second => 1.054350e+3, :british_thermal_units_per_second => 1.054350e+3,
245
+ :it_british_thermal_unit_per_second => 1.055056e+3, :it_british_thermal_units_per_second => 1.055056e+3,
246
+ :calorie_per_minute => 6.973333e-2, :calories_per_minute => 6.973333e-2,
247
+ :calorie_per_second => 4.184, :calories_per_second => 4.184,
248
+ :erg_per_second => 1.0e-7, :ergs_per_second => 1.0e-7,
249
+ :foot_pound_force_per_hour => 3.766161e-4,
250
+ :foot_pound_force_per_minute => 2.259697e-2,
251
+ :foot_pound_force_per_second => 1.355818,
252
+ :horsepower => 7.456999e+2,
253
+ :boiler_horsepower => 9.80950e+3,
254
+ :electric_horsepower => 7.46e+2,
255
+ :metric_horsepower => 7.354988e+2,
256
+ :uk_horsepower => 7.4570e+2,
257
+ :water_horsepower => 7.46043e+2,
258
+ :kilocalorie_per_minute => 6.973333*10, :kilocalories_per_minute => 6.973333*10,
259
+ :kilocalorie_per_second => 4.184e+3, :kilocalories_per_second => 4.184e+3,
260
+ :ton_of_refrigeration => 3.516853e+3, :tons_of_refrigeration => 3.516853e+3
261
+ },
262
+ :pressure => {
263
+ :pascal => 1.0, :pascals => 1.0, :Pa => 1.0,
264
+ :atmosphere => 1.01325e+5, :atmospheres => 1.01325e+5,
265
+ :technical_atmosphere => 9.80665e+4, :technical_atmospheres => 9.80665e+4,
266
+ :bar => 1.0e+5, :bars => 1.0e+5,
267
+ :centimeter_of_mercury => 1.333224e+3, :centimeters_of_mercury => 1.333224e+3,
268
+ :centimeter_of_water => 98.0665, :centimeters_of_water => 98.0665, :gram_force_per_square_centimeter => 98.0665,
269
+ :dyne_per_square_centimeter => 1.0e-1, :dynes_per_square_centimeter => 1.0e-1,
270
+ :foot_of_mercury => 4.063666e+4, :feet_of_mercury => 4.063666e+4,
271
+ :foot_of_water => 2.989067e+3, :feet_of_water => 2.989067e+3,
272
+ :inch_of_mercury => 3.386389e+3, :inches_of_mercury => 3.386389e+3,
273
+ :inch_of_water => 2.490889e+2, :inches_of_water => 2.490889e+2,
274
+ :kilogram_force_per_square_centimeter => 9.80665e+4,
275
+ :kilogram_force_per_square_meter => 9.80665,
276
+ :kilogram_force_per_square_millimeter => 9.80665e+6,
277
+ :kip_per_square_inch => 6.894757e+6, :kips_per_square_inch => 6.894757e+6, :ksi => 6.894757e+6,
278
+ :millibar => 1.0e+2, :mbar => 1.0e+2, :millibars => 1.0e+2, :mbars => 1.0e+2,
279
+ :millimeter_of_mercury => 1.333224e+2, :millimeters_of_mercury => 1.333224e+2,
280
+ :millimeter_of_water => 9.80665, :millimeters_of_water => 9.80665,
281
+ :poundal_per_square_foot => 1.488164, :poundals_per_square_foot => 1.488164,
282
+ :pound_force_per_square_foot => 47.88026,
283
+ :pound_force_per_square_inch => 6.894757e+3, :psi => 6.894757e+3,
284
+ :torr => 1.333224e+2, :torrs => 1.333224e+2
285
+ },
286
+ :radioactivity => {
287
+ :becquerel => 1.0, :becquerels => 1.0, :Bq => 1.0,
288
+ :curie => 3.7e+10, :curies => 3.7e+10, :Ci => 3.7e+10
289
+ },
290
+ :temperature => {
291
+ :kelvin => 1.0, :K => 1.0,
292
+
293
+ :celsius => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }], :centrigrade => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }],
294
+ :degree_celsius => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }], :degree_centrigrade => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }],
295
+ :degrees_celsius => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }], :degrees_centrigrade => [Proc.new{ |t| t + 273.15 }, Proc.new{ |t| t - 273.15 }],
296
+ :fahrenheit => [Proc.new{ |t| (t + 459.67) * (5.0/9.0) }, Proc.new{ |t| t * (9.0/5.0) - 459.67 }],
297
+ :degree_fahrenheit => [Proc.new{ |t| (t + 459.67) * (5.0/9.0) }, Proc.new{ |t| t * (9.0/5.0) - 459.67 }],
298
+ :degrees_fahrenheit => [Proc.new{ |t| (t + 459.67) * (5.0/9.0) }, Proc.new{ |t| t * (9.0/5.0) - 459.67 }],
299
+ :rankine => 1.8, :rankines => 1.8
300
+ },
301
+ :time => {
302
+ :second => 1.0, :seconds => 1.0, :s => 1.0,
303
+ :minute => 60.0, :minutes => 60.0, :min => 60.0,
304
+ :sidereal_minute => 5.983617, :sidereal_minutes => 5.983617,
305
+ :hour => 3600.0, :hours => 3600.0, :hr => 3600.0, :h => 3600.0,
306
+ :sidereal_hour => 3.590170e+3, :sidereal_hours => 3.590170e+3,
307
+ :day => 86400.0, :days => 86400.0,
308
+ :sidereal_day => 8.616409e+4, :sidereal_days => 8.616409e+4,
309
+ :shake => 1.0e-8, :shakes => 1.0e-8,
310
+ :year => 3.1536e+7, :years => 3.1536e+7,
311
+ :sidereal_year => 3.155815e+7, :sidereal_years => 3.155815e+7,
312
+ :tropical_year => 3.155693e+7, :tropical_years => 3.155693e+7,
313
+ #unusual measurements
314
+ :jiffy => 0.01, :jiffies => 0.01,
315
+ :microfortnight => 1.2096, :microfortnights => 1.2096,
316
+ :megaannum => 3.1536e+16, :Ma => 3.1536e+16, :megaannums => 3.1536e+16,
317
+ :galactic_year => 7.884e+18, :galactic_years => 7.884e+18, :GY => 7.884e+18
318
+ },
319
+ :volume => {
320
+ :litre => 1.0, :liter => 1.0, :litres => 1.0, :liters => 1.0, :l => 1.0, :L => 1.0,
321
+ :barrel => 1.589873e+2, :barrels => 1.589873e+2,
322
+ :bushel => 3.523907e+1, :bushels => 3.523907e+1,
323
+ :cubic_meter => 1000.0, :cubic_meters => 1000.0,
324
+ :cup => 2.365882e-1, :cups => 2.365882e-1,
325
+ :imperial_fluid_ounce => 0.0284130742, :imperial_fluid_ounces => 0.0284130742,
326
+ :ounce => 0.0295735296, :ounces => 0.0295735296, :fluid_ounce => 0.0295735296, :fluid_ounces => 0.0295735296,
327
+ :imperial_gallon => 4.54609, :imperial_gallons => 4.54609,
328
+ :gallon => 3.785412, :gallons => 3.785412, :gals => 3.785412, :Gals => 3.785412,
329
+ :imperial_gill => 1.420653e-1, :imperial_gills => 1.420653e-1,
330
+ :gill => 1.182941e-1, :gills => 1.182941e-1, :gi => 1.182941e-1,
331
+ :pint => 5.506105e-1, :pints => 5.506105e-1,
332
+ :liquid_pint => 4.731765e-1, :liquid_pints => 4.731765e-1,
333
+ :quart => 1.101221, :quarts => 1.101221,
334
+ :liquid_quart => 9.463529e-1, :liquid_quarts => 9.463529e-1,
335
+ :tablespoon => 0.0147867648, :tablespoons => 0.0147867648,
336
+ :teaspoon => 0.00492892159, :teaspoons => 0.00492892159,
337
+ #unusual measurements
338
+ :sydharb => 5.0e+11, :sydharbs => 5.0e+11
339
+ }
340
+ }
341
+ end
@@ -0,0 +1,96 @@
1
+ require 'singleton'
2
+
3
+ module Metamorphosis
4
+ class Engine
5
+ include Singleton
6
+
7
+ attr_reader :registry
8
+
9
+ def numeric_to_unit_value(numeric, unit_name)
10
+ exponent, unit_symbol = @parser.parse(unit_name)
11
+ return nil unless @registry.include?(unit_symbol)
12
+ UnitValue.new(unit_symbol, numeric, exponent)
13
+ end
14
+
15
+ def initialize
16
+ reset!
17
+ end
18
+
19
+ def reset!
20
+ @registry = UnitRegistry.new
21
+ @parser = PrefixParser.new(DEFAULT_PREFIXES, @registry)
22
+ end
23
+
24
+ def common_unit_category(source, dest)
25
+ source_categories = @registry.unit_categories(source)
26
+ dest_categories = @registry.unit_categories(dest)
27
+
28
+ category = (source_categories & dest_categories).first
29
+ end
30
+
31
+ def convert_to(dest_unit_name, source)
32
+ return source if dest_unit_name.to_sym == source.unit_symbol
33
+
34
+ exponent, dest_unit_symbol = @parser.parse(dest_unit_name)
35
+ return unless @registry.include?(dest_unit_symbol)
36
+
37
+ category = common_unit_category(source.unit_symbol, dest_unit_symbol)
38
+ unless category
39
+ raise IncompatibleUnitsError,
40
+ "Cannot convert from #{source.unit_symbol} to #{dest_unit_symbol}"
41
+ end
42
+
43
+ value = to_base_value(category, source)
44
+
45
+ from_base_value(category, dest_unit_symbol, value, exponent)
46
+ end
47
+
48
+ def from_base_value(category, dest_unit_symbol, value, exponent)
49
+ conversion_factor = @registry.conversion_factor(category, dest_unit_symbol)
50
+ if conversion_factor.is_a?(Array)
51
+ new_unit_value = conversion_factor[1].call(value)
52
+ else
53
+ new_unit_value = value / (exponent * conversion_factor)
54
+ end
55
+ UnitValue.new(dest_unit_symbol, new_unit_value)
56
+ end
57
+
58
+ def to_base_value(category, source_unit)
59
+ conversion_factor = @registry.conversion_factor(category, source_unit.unit_symbol)
60
+ if(conversion_factor.is_a?(Array))
61
+ conversion_factor[0].call(source_unit.value) * source_unit.exponent
62
+ else
63
+ source_unit.to_f * conversion_factor
64
+ end
65
+ end
66
+
67
+ def register_unit(category, symbols, value)
68
+ value = value.is_a?(UnitValue) ? to_base_value(category, value) : value
69
+ symbols = Array(symbols)
70
+ symbols.each do |unit_symbol|
71
+ @registry.register(category, unit_symbol, value)
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ def self.engine
78
+ Engine.instance
79
+ end
80
+
81
+ def self.register_predefined_units
82
+ PRE_DEFINED_UNITS.each do |category, units|
83
+ units.each do |unit_symbol, value|
84
+ engine.register_unit(category, unit_symbol, value)
85
+ end
86
+ end
87
+ end
88
+
89
+ def self.reset!
90
+ engine.reset!
91
+ end
92
+
93
+ def self.register_unit(category, symbols, value)
94
+ engine.register_unit(category, symbols, value)
95
+ end
96
+ end
@@ -0,0 +1,4 @@
1
+ module Metamorphosis
2
+ class Error < StandardError; end
3
+ class IncompatibleUnitsError < Error; end
4
+ end
@@ -0,0 +1,35 @@
1
+ module Metamorphosis
2
+ class PrefixParser
3
+ attr_reader :prefixes
4
+
5
+ def initialize(prefixes, available_units)
6
+ @prefixes = prefixes
7
+ @available_units = available_units
8
+ end
9
+
10
+ # Given a known set of unit names, returns the prefix value,
11
+ # and the base unit name
12
+ def parse(unit_text)
13
+ unit_text = unit_text.to_s
14
+ @prefixes.each do |prefix, value|
15
+ unit = parse_unit(unit_text, prefix)
16
+ next unless unit
17
+
18
+ return [value, unit]
19
+ end
20
+ [1.0, unit_text.to_sym]
21
+ end
22
+
23
+
24
+ #############################################
25
+ private
26
+
27
+ def parse_unit(unit_text, prefix)
28
+ md = /^#{prefix}(.+)/.match(unit_text)
29
+ return unless md
30
+ unit = md[1].to_sym
31
+
32
+ @available_units.include?(unit) ? unit : nil
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ module Metamorphosis
2
+ class UnitRegistry
3
+
4
+ def initialize
5
+ @categories = Hash.new{|h,k| h[k] = {} }
6
+ @unit_category_lookup = Hash.new{|h,k| h[k] = Set.new }
7
+ end
8
+
9
+ def register(category, unit, conversion)
10
+ category_symbol = category.to_sym
11
+ unit_symbol = unit.to_sym
12
+ @categories[category_symbol][unit_symbol] = conversion
13
+ @unit_category_lookup[unit_symbol] << category_symbol
14
+ end
15
+
16
+ def category_names
17
+ @categories.keys
18
+ end
19
+
20
+ def unit_categories(unit)
21
+ unit_symbol = unit.is_a?(UnitValue) ? unit.unit_symbol : unit.to_sym
22
+ @unit_category_lookup[unit_symbol]
23
+ end
24
+
25
+
26
+ def conversion_factor(category, unit)
27
+ @categories[category.to_sym][unit]
28
+ end
29
+
30
+ def include?(unit)
31
+ @unit_category_lookup.include?(unit.to_sym)
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,54 @@
1
+ module Metamorphosis
2
+ class UnitValue
3
+ include Comparable
4
+
5
+ attr_reader :unit_symbol, :value, :exponent
6
+
7
+ def initialize(unit_symbol, value, exponent = 1.0)
8
+ @unit_symbol = unit_symbol.to_sym
9
+ @value = value
10
+ @exponent = exponent.to_f
11
+ end
12
+
13
+ def to_s
14
+ "#{self.to_f} #{unit_symbol}"
15
+ end
16
+
17
+ def to_f
18
+ @exponent * @value
19
+ end
20
+
21
+ def to_i
22
+ to_f.to_i
23
+ end
24
+
25
+ def <=>(other_unit)
26
+ unless other_unit.is_a?(UnitValue) || other_unit.is_a?(Numeric)
27
+ raise ArgumentError,
28
+ "Unable to compare #{self.to_s} with #{other_unit.class}"
29
+ end
30
+
31
+ # Assume numeric values are of the same unit type
32
+ return self.to_f <=> other_unit if other_unit.is_a?(Numeric)
33
+
34
+ # Convert the unit if they're not the same unit already
35
+ unless @unit_symbol == other_unit.unit_symbol
36
+ other_unit = other_unit.to(@unit_symbol)
37
+ end
38
+
39
+ self.to_f <=> other_unit.to_f
40
+ end
41
+
42
+ def to(unit_symbol = nil)
43
+ return self unless unit_symbol
44
+ Metamorphosis.engine.convert_to(unit_symbol, self)
45
+ end
46
+ alias_method :as, :to
47
+
48
+ def method_missing method_name, *args, &block
49
+ self.to(method_name) ||
50
+ super( method_name, *args, &block )
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,3 @@
1
+ module Metamorphosis
2
+ VERSION="0.1"
3
+ end
data/lib/numeric.rb ADDED
@@ -0,0 +1,9 @@
1
+ class Numeric
2
+
3
+ def method_missing method_name, *args, &block
4
+ engine = Metamorphosis::Engine.instance
5
+ value = engine.numeric_to_unit_value(self, method_name)
6
+ value || super( method_name, *args, &block )
7
+ end
8
+
9
+ end
@@ -0,0 +1,15 @@
1
+ require 'rubygems' unless defined? Gem
2
+ require File.dirname(__FILE__) + "/lib/metamorphosis/version"
3
+ Gem::Specification.new do |s|
4
+ s.name = "metamorphosis"
5
+ s.version = Metamorphosis::VERSION
6
+ s.authors = ["Ryan Stawarz"]
7
+ s.email = "rstawarz@wegowise.com"
8
+ s.homepage = "http://github.com/wegowise/metamorphosis"
9
+ s.summary = "A library for enabling conversions between units"
10
+ s.description = "A library for enabling conversions between units"
11
+ s.add_development_dependency('rspec')
12
+ s.required_rubygems_version = ">= 1.3.6"
13
+ s.files = Dir.glob(%w[{lib,spec}/**/*.rb bin/* [A-Z]*.{txt,rdoc,md} ext/**/*.{rb,c}]) + %w{metamorphosis.gemspec}
14
+ s.license = 'MIT'
15
+ end
@@ -0,0 +1,104 @@
1
+ require "spec_helper"
2
+
3
+ describe Metamorphosis::Engine do
4
+
5
+ let!(:engine){ Metamorphosis::Engine.instance }
6
+
7
+ before{ Metamorphosis.register_predefined_units }
8
+ after { Metamorphosis.reset! }
9
+
10
+ describe "#numeric_to_unit_value" do
11
+ it "Creates a UnitValue from a numeric value and a unit name" do
12
+ engine.numeric_to_unit_value(42.0, 'J').
13
+ should == Metamorphosis::UnitValue.new(:J, 42.0)
14
+ end
15
+
16
+ it "Creates a UnitValue from a numeric value and a unit name with a prefix" do
17
+ val = engine.numeric_to_unit_value(42.0, 'kJ')
18
+ val.should == Metamorphosis::UnitValue.new(:J, 42.0, 1_000)
19
+ val.to_f.should == 42_000
20
+ end
21
+
22
+ it "returns nil when the unit_name is not recognized" do
23
+ engine.numeric_to_unit_value(1.0, 'junk').should be_nil
24
+ end
25
+ end
26
+
27
+ describe "#convert_to" do
28
+ it "converts 16 ounces to cups" do
29
+ engine.convert_to(:cups, 16.ounces).to_f.
30
+ should be_within(0.000001).of(2)
31
+ end
32
+
33
+ it "converts 73 degress F to celsius" do
34
+ engine.convert_to(:celsius, 73.degree_fahrenheit).to_f.
35
+ should be_within(0.0001).of(22.7778)
36
+ end
37
+
38
+ it "converts btu's to kilowatt_hour" do
39
+ engine.convert_to(:kilowatt_hours, 1054.350.british_thermal_units).
40
+ to_f.should be_within(0.000001).of(0.3087927)
41
+ end
42
+
43
+ it "convert joules's to therms" do
44
+ engine.convert_to(:therms, 1.J).to_f.
45
+ should be_within(0.0001).of(1/1.05506e+8)
46
+ end
47
+
48
+ it "converts to the same unit" do
49
+ engine.convert_to(:therms, 44.therms).to_f.
50
+ should == 44
51
+ end
52
+ end
53
+
54
+ describe "#to_base_value" do
55
+ it "converts units into base unit values" do
56
+ engine.to_base_value(:energy, 1.british_thermal_units).
57
+ should == 1_054.35
58
+ end
59
+
60
+ it "uses the first proc to convert to the base value when provided" do
61
+ engine.to_base_value(:temperature, 1.3.celsius).
62
+ should == 274.45
63
+ end
64
+ end
65
+
66
+ describe "#from_base_values" do
67
+ it "converts from base values" do
68
+ engine.from_base_value(:energy, :british_thermal_units, 1_054.35, 1.0).
69
+ should == 1.british_thermal_units
70
+ end
71
+
72
+ it "converts from base values using the last proc when provided" do
73
+ engine.from_base_value(:temperature, :celsius, 274.45, 1.0).to_f.
74
+ should be_within(0.00000000001).of(1.3)
75
+ end
76
+ end
77
+
78
+ # Incompatible type checking (i.e. area to volume
79
+ it "raises an Error when the unit types are not compatible" do
80
+ expect{ engine.convert_to(:square_meter, 16.ounces) }.
81
+ to raise_error(Metamorphosis::IncompatibleUnitsError)
82
+ end
83
+
84
+ it "will register multiple units symbosl to the same value" do
85
+ engine.register_unit(:stuff, [:value1a, :value1b], 1.0)
86
+ engine.register_unit(:stuff, [:value2c, :value2d], 2.0)
87
+
88
+ 1.value1b.value1a.to_f.should == 1.value1a.to_f
89
+ 1.value1a.should == 1.value1b
90
+ 1.value2c.value1a.to_f.should == 2.0
91
+ 1.value2c.should == 2.value1a
92
+ 1.value2c.should == 1.value2d
93
+ 1.value2d.should == 2.value1b
94
+ end
95
+
96
+ it "#register_units allows units to be defined based on other units" do
97
+ Metamorphosis.reset!
98
+ Metamorphosis.register_unit(:energy, :btu, 1.0)
99
+ Metamorphosis.register_unit(:energy, :therms, 100_000.btu)
100
+ Metamorphosis.register_unit(:energy, :kwh, 0.03413.therms)
101
+ 1.kwh.to.btu.to_f.should == 3413.0
102
+ end
103
+
104
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Metamorphosis::PrefixParser do
4
+ let!(:available_units) {Metamorphosis::SI_UNITS }
5
+ let!(:prefixes) { Metamorphosis::DEFAULT_PREFIXES }
6
+ let!(:parser) {Metamorphosis::PrefixParser.new(prefixes, available_units)}
7
+
8
+ [:meter, :joule].each do |unit|
9
+ Metamorphosis::DEFAULT_PREFIXES.each do |prefix, value|
10
+ new_unit = "#{prefix}#{unit}"
11
+ it "parses #{new_unit}as [#{value}, #{unit}]" do
12
+ parser.parse(new_unit).should == [value, unit.to_sym]
13
+ end
14
+ end
15
+ end
16
+
17
+ it "should parse kJ" do
18
+ parser.parse("kJ").should == [1000.0, :J]
19
+ end
20
+
21
+ it "should return the unit with value of 1.0 for unknown prefix" do
22
+ parser.parse("crazystuff").should == [1.0, :crazystuff]
23
+ end
24
+
25
+ it "should return the unit with value of 1.0 for unknown unit" do
26
+ parser.parse("kilojunk").should == [1.0, :kilojunk]
27
+ end
28
+
29
+ it "should allow prefixes to be overridden" do
30
+ prefixes = { :yotta => 2**80, :Y => 2**80,
31
+ :zetta => 2**70, :Z => 2**70,
32
+ :exa => 2**60, :E => 2**60,
33
+ :peta => 2**50, :P => 2**50,
34
+ :tera => 2**40, :T => 2**40,
35
+ :giga => 2**30, :G => 2**30,
36
+ :mega => 2**20, :M => 2**20,
37
+ :kilo => 2**10, :k => 2**10 }
38
+ parser = Metamorphosis::PrefixParser.new(prefixes, [:byte])
39
+ parser.parse("kbyte").should == [1024, :byte]
40
+
41
+ parser.parse("Mbyte").should == [1048576, :byte]
42
+ end
43
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Metamorphosis::UnitRegistry do
4
+
5
+ let!(:registry) { Metamorphosis::UnitRegistry.new }
6
+ let!(:subject) { registry }
7
+
8
+ before do
9
+ registry.register(:wegowise, :btu, 1)
10
+ registry.register(:wegowise, :therms, 100_000)
11
+ registry.register(:other, :btu, 22)
12
+ registry.register(:junk, :whatchamakalit, 0.0000001)
13
+ end
14
+
15
+ its(:category_names) { should match_array [:wegowise, :other, :junk] }
16
+
17
+ it "keeps different conversion factors for units across categories" do
18
+ registry.conversion_factor(:wegowise, :btu).
19
+ should_not == registry.conversion_factor(:other, :btu)
20
+ end
21
+
22
+ it "returns the set of categories a unit belongs to" do
23
+ registry.unit_categories(:btu).to_a.should match_array [:wegowise, :other]
24
+ registry.unit_categories(:therms).to_a.should == [:wegowise]
25
+ end
26
+
27
+ it "tracks conversion factors for units" do
28
+ registry.conversion_factor(:wegowise, :btu).should == 1
29
+ registry.conversion_factor(:wegowise, :therms).should == 100_000
30
+ registry.conversion_factor(:other, :btu).should == 22
31
+ end
32
+
33
+ it "tracks which units have been registered" do
34
+ registry.include?(:btu).should be_true
35
+ registry.include?(:therms).should be_true
36
+ registry.include?(:joules).should be_false
37
+ end
38
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe Metamorphosis::UnitValue do
4
+
5
+ before{ Metamorphosis.register_predefined_units }
6
+ after { Metamorphosis.reset! }
7
+
8
+ let!(:unit) { Metamorphosis::UnitValue.new('therms', 1.3, 1_000) }
9
+ subject{ unit }
10
+
11
+ its(:unit_symbol){ should == :therms }
12
+ its(:exponent){ should == 1_000 }
13
+ its(:value){ should == 1.3 }
14
+ its(:to_s){ should == '1300.0 therms' }
15
+ its(:to_f){ should == 1300.0 }
16
+
17
+ # Comparisons between the same unit
18
+ it{ should be == Metamorphosis::UnitValue.new(:therms, 1_300) }
19
+ it{ should be > Metamorphosis::UnitValue.new(:therms, 1_290) }
20
+ it{ should be < Metamorphosis::UnitValue.new(:therms, 1_310) }
21
+
22
+ # Comparisons between different units
23
+ it{ should be > Metamorphosis::UnitValue.new(:J, 1_000) }
24
+ it{ should be == Metamorphosis::UnitValue.new(:J, 1.05506e+8 * 1_300) }
25
+ it{ should be < Metamorphosis::UnitValue.new(:J, 1.05506e+8 * 1_400) }
26
+
27
+ # Should not compare units that are not alike (i.e. energy vs. distance)
28
+ it{ should_not eq(Metamorphosis::UnitValue.new(:meters, 100)) }
29
+
30
+ it "compares like units" do
31
+ Metamorphosis::UnitValue.new('therms', 85.30320550490019).should ==
32
+ Metamorphosis::UnitValue.new('kilowatt_hour', 2_500)
33
+ end
34
+
35
+ # Don't compare non unit like things
36
+ it{ should_not be == :x }
37
+
38
+ it "raises ArgumentError comparing non numeric/UnitValues with UnitValue" do
39
+ expect{ unit <=> :x }.to raise_error(ArgumentError)
40
+ end
41
+
42
+ # Assume numeric values are of the same unit
43
+ it { should be == 1_300 }
44
+
45
+
46
+ it "returns itself when to/as method receives no parameters" do
47
+ unit.to.should === unit
48
+ unit.as.should === unit
49
+ end
50
+
51
+ it "delegates conversion to the Metamorphosis::Engine" do
52
+ Metamorphosis.engine.should_receive(:convert_to).with(:J, unit)
53
+ unit.to(:J)
54
+ end
55
+
56
+ it "delegates missing methods to the Metamorphosis::Engine" do
57
+ Metamorphosis.engine.should_receive(:convert_to).with(:J, unit).
58
+ and_return("cooking with fire!")
59
+ unit.to(:J).should == "cooking with fire!"
60
+ end
61
+
62
+ it "is a good method_missing citizen when Metamorphosis doesn't know how
63
+ to convert to the given unit" do
64
+ Metamorphosis.engine.should_receive(:convert_to).with(:J, unit).
65
+ and_return(nil)
66
+ expect{ unit.J }.to raise_error(NoMethodError)
67
+ end
68
+
69
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe Metamorphosis do
4
+ it "Exposes Metamorphosis::Engine as 'engine'" do
5
+ Metamorphosis.engine.should === Metamorphosis::Engine.instance
6
+ end
7
+
8
+ it "registers the units defined as constants" do
9
+ Metamorphosis.register_predefined_units
10
+ 1.respond_to?(:kwh)
11
+ 1.respond_to?(:kilowatt_hour)
12
+ end
13
+
14
+ it "exposes 'register_unit' from engine" do
15
+ Metamorphosis.engine.should_receive(:register_unit).with(:a, :b, :c)
16
+ Metamorphosis.register_unit(:a, :b, :c)
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Numeric do
4
+
5
+ it "delegates missing method calls to the Metamorphosis::Engine" do
6
+ engine = Metamorphosis::Engine.instance
7
+ engine.should_receive(:numeric_to_unit_value).with(1.3, :J).
8
+ and_return('eureka!')
9
+
10
+ 1.3.J.should == 'eureka!'
11
+ end
12
+
13
+ it "raises a method not found exception when the engine returns an empty result" do
14
+ engine = Metamorphosis::Engine.instance
15
+ engine.should_receive(:numeric_to_unit_value).with(1.3, :J).
16
+ and_return(nil)
17
+ expect{ 1.3.J }.to raise_error(NoMethodError)
18
+ end
19
+
20
+ end
21
+
@@ -0,0 +1,19 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
18
+
19
+ require 'metamorphosis'
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: metamorphosis
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ryan Stawarz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: A library for enabling conversions between units
31
+ email: rstawarz@wegowise.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - lib/metamorphosis/constants.rb
37
+ - lib/metamorphosis/engine.rb
38
+ - lib/metamorphosis/errors.rb
39
+ - lib/metamorphosis/prefix_parser.rb
40
+ - lib/metamorphosis/unit_registry.rb
41
+ - lib/metamorphosis/unit_value.rb
42
+ - lib/metamorphosis/version.rb
43
+ - lib/metamorphosis.rb
44
+ - lib/numeric.rb
45
+ - spec/lib/metamorphosis/engine_spec.rb
46
+ - spec/lib/metamorphosis/prefix_parser_spec.rb
47
+ - spec/lib/metamorphosis/unit_registry_spec.rb
48
+ - spec/lib/metamorphosis/unit_value_spec.rb
49
+ - spec/lib/metamorphosis_spec.rb
50
+ - spec/lib/numeric_spec.rb
51
+ - spec/spec_helper.rb
52
+ - LICENSE.txt
53
+ - README.md
54
+ - metamorphosis.gemspec
55
+ homepage: http://github.com/wegowise/metamorphosis
56
+ licenses:
57
+ - MIT
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: 1.3.6
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 1.8.24
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: A library for enabling conversions between units
80
+ test_files: []