alchemist 0.1.5 → 0.1.6

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: 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