alchemist 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 971b2a4f87be414e30ada4d1f1f34465c634fe60
4
- data.tar.gz: d997c55e956f6d2174712a7a9f9fa566a793abf3
3
+ metadata.gz: 09cdd7bc72d33ef49f70bfa21e7a6b98bc56ca35
4
+ data.tar.gz: 5930f598e0adec3f2a8b3e3e2030fd61b9c48234
5
5
  SHA512:
6
- metadata.gz: cf02dbbd813adbdbaa066e712213fe1e09c751d87507b2b8bdac5d67531ac6e7d7b9eada8d090258dcbfae0ee2c818c279e67c11ce0d6ac6498ed2e3f02eaacb
7
- data.tar.gz: 4d5c6dd3011d8c984e7b9eda8df286e92489b6c9f49235b4dca1e05137b9931130c090698f7d8e419e9d62d5fa18ce0f470a23b146f95ee8e95624f7c2a77655
6
+ metadata.gz: 72133a2fa6b707b2e52e6cb5354506d364b176aaab25383b9db8f341be847fa2622a89e888fc3adeb8021f2e347b210961a2fca687d4278a5807da5d41827bc0
7
+ data.tar.gz: b6ded515a9ebd212ace47ba64a91a9f44619f757457f27a8ae384edf380b327312e5223c444122ae5e3a2552c9d1330964c99e115f88c2e66ac6315f31fc8b3d
@@ -1,24 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- alchemist (0.1.4)
4
+ alchemist (0.1.5)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- coderay (1.0.8)
10
- method_source (0.8.1)
11
- pry (0.9.12)
12
- coderay (~> 1.0.5)
13
- method_source (~> 0.8)
14
- slop (~> 3.4)
9
+ diff-lcs (1.2.4)
15
10
  rake (10.0.3)
16
- slop (3.4.3)
11
+ rspec (2.14.1)
12
+ rspec-core (~> 2.14.0)
13
+ rspec-expectations (~> 2.14.0)
14
+ rspec-mocks (~> 2.14.0)
15
+ rspec-core (2.14.3)
16
+ rspec-expectations (2.14.0)
17
+ diff-lcs (>= 1.1.3, < 2.0)
18
+ rspec-mocks (2.14.1)
17
19
 
18
20
  PLATFORMS
19
21
  ruby
20
22
 
21
23
  DEPENDENCIES
22
24
  alchemist!
23
- pry
24
25
  rake
26
+ rspec
data/README.md CHANGED
@@ -9,113 +9,85 @@ code more readable.
9
9
 
10
10
  Having code that looks like this is meaningless
11
11
 
12
- miles = 8 * 1609.344
12
+ ```ruby
13
+ miles = 8 * 1609.344
14
+ ```
13
15
 
14
16
  You could add comments
15
17
 
16
- miles = 8 * 1609.344 # converting meters to miles
18
+ ```ruby
19
+ miles = 8 * 1609.344 # converting meters to miles
20
+ ```
17
21
 
18
22
  But why not have this!
19
23
 
20
- 8.meters.to.miles
24
+ ```ruby
25
+ 8.meters.to.miles
26
+ ```
21
27
 
22
28
  You can even perform mathematical operations
23
29
 
24
- 10.kilometers + 1.mile # 11.609344 kilometers
30
+ ```ruby
31
+ 10.kilometers + 1.mile # 11.609344 kilometers
32
+ ```
25
33
 
26
34
  Handling bytes now works according to the JEDEC memory standard
27
35
 
28
- 1.kb.to.b.to_f == 1024.0
36
+ ```ruby
37
+ 1.kb.to.b.to_f == 1024.0
38
+ ```
29
39
 
30
- To switch to the IEC memory standard, force SI units with
40
+ Converting distance of arc length on Earth to an (approximate) corresponding spherical geometry angle can be done with
31
41
 
32
- Alchemist::use_si = true
42
+ ```ruby
43
+ require 'alchemist/geospatial'
44
+ 1.mile.geospatial.to.degree == 0.014457066992474555
45
+ ```
33
46
 
34
- <strong>You may also register your own units</strong>
47
+ To switch to the IEC memory standard, force SI units with
35
48
 
36
- Alchemist.register(:distance, [:beard_second, :beard_seconds], 5.angstroms)
49
+ ```ruby
50
+ Alchemist::use_si = true
51
+ ```
37
52
 
38
- Thanks to <a href='http://github.com/simonmenke'>simonmenke</a> you can
39
- now do comparisons without having to convert to floats like so:
53
+ To see all the units alchemist has built in conversion for, check out the [units file](lib/alchemist/data/units.yml)
40
54
 
41
- 5.grams == 0.005.kilograms
55
+ <strong>You may also register your own units</strong>
56
+
57
+ ```ruby
58
+ Alchemist.register(:distance, [:beard_second, :beard_seconds], 5.angstroms)
59
+ ```
42
60
 
43
61
  Installation
44
62
  ------------
45
63
 
46
64
  gem install alchemist
47
65
 
48
- Usage
66
+ Setup
49
67
  -----
50
68
 
51
- require 'rubygems'
52
- require 'alchemist'
53
-
54
- Or if you’re using rails
55
-
56
- gem 'alchemist'
57
-
58
- Alchemist has conversions for:
59
- ------------------------------
60
-
61
- ### Distance
62
-
63
- - metres or meters
64
- - fermis
65
- - microns
66
- - chains
67
- - inches
68
- - microinches
69
- - mils
70
- - rods
71
- - leagues
72
- - feet
73
- - yards
74
- - miles
75
- - astronomical\_units
76
- - light\_years
77
- - parsecs
78
- - nautical\_miles
79
- - admirality\_miles
80
- - fathoms
81
- - cable\_lengths
82
- - angstroms
83
- - picas
84
- - printer\_picas
85
- - points
86
- - printer\_points
87
-
88
- ### Mass
89
-
90
- - grams or grammes
91
- - carats
92
- - ounces
93
- - pennyweights
94
- - pounds
95
- - troy\_pounds or apothecary\_pounds
96
- - slugs
97
- - assay\_tons
98
- - metric\_tons
99
- - tons or short\_tons
100
-
101
- ### Volume
102
-
103
- - litres or liters
104
- - barrels
105
- - bushels
106
- - cubic\_meters
107
- - cups
108
- - imperial\_fluid\_ounces
109
- - fluid\_ounces
110
- - imperial\_gallons
111
- - gallons
112
- - imperial\_gills
113
- - gills
114
- - pints
115
- - liquid\_pints
116
- - quarts
117
- - liquid\_quarts
118
- - tablespoons
119
- - teaspoons
120
-
121
- ### And many more checkout **lib/alchemist.rb** for the rest
69
+ In order for methods like `1.meter` to work, you'll either need to setup Alchemist yourself:
70
+
71
+ ```ruby
72
+ Alchemist.setup # This will load every category of measurement
73
+ ```
74
+
75
+ if you only want to use one category for conversions you can load it individually:
76
+
77
+ ```ruby
78
+ Alchemist.setup('distance') # This will load only distance
79
+ ```
80
+
81
+ Rails Warning
82
+ -------------
83
+
84
+ 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
+
86
+ ```ruby
87
+ Alchemist.measure(10, :bytes)
88
+ ```
89
+
90
+ License
91
+ -------
92
+
93
+ Alchemist is licensed under the MIT license as specified in the [gemspec](alchemist.gemspec)
data/Rakefile CHANGED
@@ -1,15 +1,6 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rake'
3
- require 'rake/testtask'
3
+ require 'rspec/core/rake_task'
4
4
 
5
- task :default => [:test]
6
- task :test => ['test:units']
7
-
8
- namespace :test do
9
- Rake::TestTask.new(:units) do |test|
10
- test.libs << 'test'
11
- test.ruby_opts << '-rubygems'
12
- test.pattern = 'test/*.rb'
13
- test.verbose = true
14
- end
15
- end
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ task default: :spec
@@ -11,10 +11,12 @@ Gem::Specification.new do |gem|
11
11
  gem.homepage = 'http://github.com/halogenandtoast/alchemist'
12
12
  gem.summary = 'Conversions... like you\'ve never seen them before!'
13
13
  gem.description = 'Conversions... like you\'ve never seen them before!!'
14
+ gem.license = 'MIT'
14
15
 
15
16
  gem.files = `git ls-files`.split($/)
16
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
18
  gem.require_paths = ["lib"]
18
19
 
19
20
  gem.add_development_dependency 'rake'
21
+ gem.add_development_dependency 'rspec'
20
22
  end
@@ -1,31 +1,32 @@
1
- require "alchemist/units"
2
- require "alchemist/compound_numeric_conversion"
3
- require "alchemist/numeric_conversion"
4
- require "alchemist/numeric_ext"
1
+ require "alchemist/conversion_table"
2
+ require "alchemist/measurement"
3
+ require "alchemist/compound_measurement"
4
+ require "alchemist/module_builder"
5
5
 
6
6
  module Alchemist
7
- def self.measurement value, unit, exponent = 1.0
8
- NumericConversion.new value, unit, exponent
9
- end
7
+ autoload :Earth, "alchemist/objects/planets/earth"
10
8
 
11
- def self.use_si
12
- @use_si ||= false
13
- end
9
+ DATA_DIR = File.join(File.dirname(__FILE__), "alchemist", "data")
14
10
 
15
- def self.use_si= use_si
16
- @use_si = use_si
17
- end
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")
18
15
 
19
- def self.conversion_table
20
- @conversion_table ||= ConversionTable.new.load_all
16
+ def self.setup category = nil
17
+ if category
18
+ Numeric.send(:include, ModuleBuilder.new(category).build)
19
+ else
20
+ conversion_table.keys.each { |category| Numeric.send(:include, ModuleBuilder.new(category).build) }
21
+ end
21
22
  end
22
23
 
23
- def self.operator_actions
24
- @operator_actions ||= {}
24
+ def self.measure value, unit, exponent = 1.0
25
+ Measurement.new value, unit, exponent
25
26
  end
26
27
 
27
- def self.conversions
28
- @conversions ||= load_conversions
28
+ def self.has_measurement? name
29
+ conversions.keys.include? name.to_sym
29
30
  end
30
31
 
31
32
  def self.measurement_for name
@@ -33,9 +34,9 @@ module Alchemist
33
34
  end
34
35
 
35
36
  def self.register(type, names, value)
36
-
37
37
  names = Array(names)
38
- value = value.is_a?(NumericConversion) ? value.base(type) : value
38
+ value = value.is_a?(Measurement) ? value.base(type) : value
39
+ Alchemist.conversion_table[type] ||= {}
39
40
 
40
41
  names.each do |name|
41
42
  conversions[name] ||= []
@@ -44,11 +45,6 @@ module Alchemist
44
45
  end
45
46
  end
46
47
 
47
- def self.register_operation_conversions type, other_type, operation, converted_type
48
- operator_actions[operation] ||= []
49
- operator_actions[operation] << [type, other_type, converted_type]
50
- end
51
-
52
48
  def self.parse_prefix(unit)
53
49
  matches = unit.to_s.match(prefix_matcher)
54
50
  prefix, parsed_unit = matches.captures
@@ -61,16 +57,59 @@ module Alchemist
61
57
  end
62
58
  end
63
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
+
64
102
  private
65
103
 
66
104
  def self.use_binary_prefix? unit
67
105
  !use_si && measurement_for(unit).include?(:information_storage)
68
106
  end
69
107
 
70
-
71
108
  def self.prefix_matcher
72
- keys = unit_prefixes.keys.map(&:to_s).sort{ |a,b| b.length <=> a.length }
73
- %r{^(#{keys.join('|')})?(.+)}
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
74
113
  end
75
114
 
76
115
  def self.prefixed_value_for prefix, unit
@@ -92,5 +131,3 @@ module Alchemist
92
131
  conversions
93
132
  end
94
133
  end
95
-
96
- require "alchemist/compound"
@@ -1,5 +1,5 @@
1
1
  module Alchemist
2
- class CompoundNumericConversion
2
+ class CompoundMeasurement
3
3
  attr_accessor :numerators, :denominators
4
4
 
5
5
  def initialize(numerator)
@@ -13,13 +13,12 @@ module Alchemist
13
13
  when Numeric
14
14
  @coefficient *= value
15
15
  self
16
- when Alchemist::NumericConversion
16
+ when Alchemist::Measurement
17
17
  @numerators << value
18
18
  return consolidate
19
19
  end
20
20
  end
21
21
 
22
- # TODO: minify this
23
22
  def consolidate
24
23
  compress_units
25
24
  set_coefficients
@@ -58,7 +57,7 @@ module Alchemist
58
57
 
59
58
  def method_missing(method, *attrs, &block)
60
59
  if Alchemist.measurement_for(method)
61
- @denominators << Alchemist.measurement(1, method)
60
+ @denominators << Alchemist.measure(1, method)
62
61
  consolidate
63
62
  end
64
63
  end
@@ -0,0 +1,69 @@
1
+ require 'yaml'
2
+
3
+ module Alchemist
4
+ class ConversionTable
5
+
6
+ def load_all(yaml_file)
7
+ begin
8
+ YAML.load_file(yaml_file).merge(proc_based)
9
+ rescue Psych::SyntaxError, Errno::ENOENT
10
+ nil
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def proc_based
17
+ {
18
+ :density => {
19
+ :specific_gravity => 1, :sg => 1,
20
+ :brix => [lambda{ |d| -261.3 / (d - 261.3) }, lambda{ |d| 261.3 - (261.3 / d) }],
21
+ :plato => [lambda{ |d| -260.0 / (d - 260.0) }, lambda{ |d| 260.0 - (260.0 / d) }],
22
+ :baume => [lambda{ |d| -145.0 / (d - 145.0) }, lambda{ |d| 145.0 - (145.0 / d) }]
23
+ },
24
+ :temperature => temperature
25
+ }
26
+ end
27
+
28
+ def temperature
29
+ {
30
+ :kelvin => 1.0, :K => 1.0,
31
+
32
+ :celsius => celsius_conversion,
33
+ :centrigrade => celsius_conversion,
34
+ :degree_celsius => celsius_conversion,
35
+ :degree_centrigrade => celsius_conversion,
36
+ :degrees_celsius => celsius_conversion,
37
+ :degrees_centrigrade => celsius_conversion,
38
+ :fahrenheit => fahrenheit_conversion,
39
+ :degree_fahrenheit => fahrenheit_conversion,
40
+ :degrees_fahrenheit => fahrenheit_conversion,
41
+ :rankine => 1.8, :rankines => 1.8
42
+ }
43
+ end
44
+
45
+ def to_celsius
46
+ lambda{ |t| t + 273.15 }
47
+ end
48
+
49
+ def from_celsius
50
+ lambda{ |t| t - 273.15 }
51
+ end
52
+
53
+ def celsius_conversion
54
+ [to_celsius, from_celsius]
55
+ end
56
+
57
+ def to_fahrenheit
58
+ lambda{ |t| (t - 32.0) * (5.0/9.0) + 273.15 }
59
+ end
60
+
61
+ def from_fahrenheit
62
+ lambda{ |t| (t - 273.15) * (9.0/5.0) + 32.0 }
63
+ end
64
+
65
+ def fahrenheit_conversion
66
+ [to_fahrenheit, from_fahrenheit]
67
+ end
68
+ end
69
+ end