measured 2.0.0.pre3 → 2.0.0.pre4

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: 31510659ee5ef4e555a6e90c6b02ccfbb2d00762
4
- data.tar.gz: 6d4098c941cfeb91a625c7b535a8e68857f91d87
3
+ metadata.gz: 674d14a40f494d518096818abee97059c304c311
4
+ data.tar.gz: f8303931e971c18c714e4d4ba74ec39c141fefd8
5
5
  SHA512:
6
- metadata.gz: faf9a4f655aca4e68679da9e1220ccb1c2f44ae41f7ae5fa194b711825735d3e38056e40cf8f992abaff14d6502f438d843645824951f00bbfc9cb75b77790a2
7
- data.tar.gz: cff7887f432a42af3a7e0e19c487183baed8f7c2ba251d9329211efe5c1ae950d43a54d3a4bdccda035a2f1c3585cf3a31d657a3fc639d3a2bd27be53a7ee088
6
+ metadata.gz: 5402f3214c5b44a06f979f4fe86a9dc27682a2b3bb605ab944c8a35dcda780f58e11d8be70901eeb28e61986049bbd9e26e3930d13e66170b79de20b5f8c9446
7
+ data.tar.gz: 10f00639a2bc89230c0a60ab00f58cfb27801c90262c326e6a658947b22ef4bef7208bbed33fdd9486ecc6957f2cdfc5a954622e44c71f0b89021f690fb063f1
data/README.md CHANGED
@@ -56,6 +56,20 @@ rescue Measured::UnitError
56
56
  end
57
57
  ```
58
58
 
59
+ Parse from string without having to split out the value and unit first:
60
+
61
+ ```ruby
62
+ Measured::Weight.parse("123 grams")
63
+ > #<Measured::Weight 123 g>
64
+ ```
65
+
66
+ Parse can scrub extra whitespace and split number from unit:
67
+
68
+ ```ruby
69
+ Measured::Weight.parse(" 2kg ")
70
+ > #<Measured::Weight 2 kg>
71
+ ```
72
+
59
73
  Perform addition / subtraction against other units, all represented internally as `Rational` or `BigDecimal`:
60
74
 
61
75
  ```ruby
@@ -169,15 +183,7 @@ Measured::Thing = Measured.build do
169
183
  end
170
184
  ```
171
185
 
172
- By default all names and aliases are case insensitive. If you would like to create a new unit with names and aliases that are case sensitive, specify the case sensitive flag when building your unit:
173
-
174
- ```ruby
175
- Measured::Thing = Measured.build(case_sensitive: true) do
176
- unit :base_unit, aliases: [:bu]
177
- end
178
- ```
179
-
180
- Other than case sensitivity, both classes are identical to each other. The `case_sensitive` flag, which is false by default, gets taken into account any time you attempt to reference a unit by name or alias.
186
+ All unit names are case sensitive.
181
187
 
182
188
  Values for conversion units can be defined as a string with two tokens `"number unit"` or as an array with two elements. All values will be parsed as / coerced to `Rational`. Conversion paths don't have to be direct as a conversion table will be built for all possible conversions.
183
189
 
@@ -6,8 +6,8 @@ module Measured
6
6
  class UnitError < StandardError ; end
7
7
 
8
8
  class << self
9
- def build(**kwargs, &block)
10
- builder = UnitSystemBuilder.new(**kwargs)
9
+ def build(&block)
10
+ builder = UnitSystemBuilder.new
11
11
  builder.instance_eval(&block)
12
12
 
13
13
  Class.new(Measurable) do
@@ -38,10 +38,9 @@ module Measured
38
38
  end
39
39
 
40
40
  require "measured/arithmetic"
41
+ require "measured/parser"
41
42
  require "measured/unit"
42
43
  require "measured/unit_system"
43
- require "measured/case_insensitive_unit"
44
- require "measured/case_insensitive_unit_system"
45
44
  require "measured/unit_system_builder"
46
45
  require "measured/conversion_table"
47
46
  require "measured/measurable"
@@ -65,6 +65,10 @@ class Measured::Measurable < Numeric
65
65
  def name
66
66
  to_s.split("::").last.underscore.humanize.downcase
67
67
  end
68
+
69
+ def parse(string)
70
+ new(*Measured::Parser.parse_string(string))
71
+ end
68
72
  end
69
73
 
70
74
  private
@@ -0,0 +1,37 @@
1
+ module Measured::Parser
2
+ extend self
3
+
4
+ PARSE_REGEX = /
5
+ \A # beginning of input
6
+ \s* # optionally any whitespace
7
+ ( # capture the value
8
+ -? # number can be negative
9
+ \d+ # must have some digits
10
+ (?: # do not capture
11
+ [\.\/] # period or slash to split fractional part
12
+ \d+ # some digits after it
13
+ )? # fractional part is optional
14
+ )
15
+ \s* # optionally any space between number and unit
16
+ ( # capture the unit
17
+ [a-zA-Z] # unit must start with a letter
18
+ [\w-]* # any word characters or dashes
19
+ (?: # non capturing group that is optional for multiple words
20
+ \s+ # space in the unit for multiple words
21
+ [\w-]+ # there must be something after the space
22
+ )* # allow many words
23
+ )
24
+ \s* # optionally any whitespace
25
+ \Z # end of unit
26
+ /x
27
+
28
+ def parse_string(string)
29
+ raise Measured::UnitError, "Cannot parse blank measurement" if string.blank?
30
+
31
+ result = PARSE_REGEX.match(string)
32
+
33
+ raise Measured::UnitError, "Cannot parse measurement from '#{string}'" unless result
34
+
35
+ [result.captures[0].to_r, result.captures[1]]
36
+ end
37
+ end
@@ -64,9 +64,14 @@ class Measured::Unit
64
64
  end
65
65
 
66
66
  def parse_value(tokens)
67
- tokens = tokens.split(" ", 2) if tokens.is_a?(String)
68
-
69
- raise Measured::UnitError, "Cannot parse 'number unit' or [number, unit] formatted tokens from #{tokens}." unless tokens.size == 2
67
+ case tokens
68
+ when String
69
+ tokens = Measured::Parser.parse_string(tokens)
70
+ when Array
71
+ raise Measured::UnitError, "Cannot parse [number, unit] formatted tokens from #{tokens}." unless tokens.size == 2
72
+ else
73
+ raise Measured::UnitError, "Unit must be defined as string or array, but received #{tokens}"
74
+ end
70
75
 
71
76
  [tokens[0].to_r, tokens[1].freeze]
72
77
  end
@@ -1,7 +1,6 @@
1
1
  class Measured::UnitSystemBuilder
2
- def initialize(case_sensitive: false)
2
+ def initialize
3
3
  @units = []
4
- @case_sensitive = case_sensitive
5
4
  end
6
5
 
7
6
  def unit(unit_name, aliases: [], value: nil)
@@ -10,25 +9,17 @@ class Measured::UnitSystemBuilder
10
9
  end
11
10
 
12
11
  def build
13
- unit_system_class.new(@units)
12
+ Measured::UnitSystem.new(@units)
14
13
  end
15
14
 
16
15
  private
17
16
 
18
17
  def build_unit(name, aliases: [], value: nil)
19
- unit = unit_class.new(name, aliases: aliases, value: value)
18
+ unit = Measured::Unit.new(name, aliases: aliases, value: value)
20
19
  check_for_duplicate_unit_names!(unit)
21
20
  unit
22
21
  end
23
22
 
24
- def unit_class
25
- @case_sensitive ? Measured::Unit : Measured::CaseInsensitiveUnit
26
- end
27
-
28
- def unit_system_class
29
- @case_sensitive ? Measured::UnitSystem : Measured::CaseInsensitiveUnitSystem
30
- end
31
-
32
23
  def check_for_duplicate_unit_names!(unit)
33
24
  names = @units.flat_map(&:names)
34
25
  if names.any? { |name| unit.names.include?(name) }
@@ -1,3 +1,3 @@
1
1
  module Measured
2
- VERSION = "2.0.0.pre3"
2
+ VERSION = "2.0.0.pre4"
3
3
  end
@@ -20,8 +20,9 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_runtime_dependency "activesupport", ">= 4.2"
22
22
 
23
- spec.add_development_dependency "rake", "~> 10.0"
24
- spec.add_development_dependency "minitest", "~> 5.5.1"
25
- spec.add_development_dependency "mocha", "~> 1.1.0"
23
+ spec.add_development_dependency "rake", "> 10.0"
24
+ spec.add_development_dependency "minitest", "> 5.5.1"
25
+ spec.add_development_dependency "minitest-reporters"
26
+ spec.add_development_dependency "mocha", "> 1.1.0"
26
27
  spec.add_development_dependency "pry"
27
28
  end
@@ -82,10 +82,10 @@ class Measured::MeasurableTest < ActiveSupport::TestCase
82
82
  end
83
83
 
84
84
  test ".unit_system is set and cached" do
85
- unit_system = CaseSensitiveMagic.unit_system
85
+ unit_system = Magic.unit_system
86
86
 
87
87
  assert_instance_of Measured::UnitSystem, unit_system
88
- assert_equal unit_system.__id__, CaseSensitiveMagic.unit_system.__id__
88
+ assert_equal unit_system.__id__, Magic.unit_system.__id__
89
89
  end
90
90
 
91
91
  test ".unit_names returns just the base unit names" do
@@ -94,7 +94,7 @@ class Measured::MeasurableTest < ActiveSupport::TestCase
94
94
 
95
95
  test ".unit_names_with_aliases returns all units" do
96
96
  assert_equal(
97
- %w(arcane fire fireball fireballs ice magic_missile magic_missiles ultima),
97
+ %w(arcane fire fireball fireballs ice magic\ missile magic_missile magic_missiles ultima),
98
98
  Magic.unit_names_with_aliases
99
99
  )
100
100
  end
@@ -115,6 +115,76 @@ class Measured::MeasurableTest < ActiveSupport::TestCase
115
115
  assert_equal "very complex thing", Example::VeryComplexThing.name
116
116
  end
117
117
 
118
+ test ".parse raises on nil input" do
119
+ exception = assert_raises(Measured::UnitError) do
120
+ Magic.parse(nil)
121
+ end
122
+ assert_equal "Cannot parse blank measurement", exception.message
123
+ end
124
+
125
+ test ".parse raises on blank string input" do
126
+ exception = assert_raises(Measured::UnitError) do
127
+ Magic.parse("")
128
+ end
129
+ assert_equal "Cannot parse blank measurement", exception.message
130
+ end
131
+
132
+ test ".parse raises on a single incorrect string" do
133
+ exception = assert_raises(Measured::UnitError) do
134
+ Magic.parse("arcane")
135
+ end
136
+ assert_equal "Cannot parse measurement from 'arcane'", exception.message
137
+ end
138
+
139
+ test ".parse raises on a single incorrect number" do
140
+ exception = assert_raises(Measured::UnitError) do
141
+ Magic.parse("1234")
142
+ end
143
+ assert_equal "Cannot parse measurement from '1234'", exception.message
144
+ end
145
+
146
+ test ".parse takes input with a space between" do
147
+ assert_equal Magic.new(1, :arcane), Magic.parse("1 arcane")
148
+ end
149
+
150
+ test ".parse takes input without a space" do
151
+ assert_equal Magic.new(99, :ice), Magic.parse("99ice")
152
+ end
153
+
154
+ test ".parse takes float with a space" do
155
+ assert_equal Magic.new(12.345, :arcane), Magic.parse("12.345 arcane")
156
+ end
157
+
158
+ test ".parse takes float without a space" do
159
+ assert_equal Magic.new(9.9, :magic_missile), Magic.parse("9.9magic_missile")
160
+ end
161
+
162
+ test ".parse truncates any space before and after" do
163
+ assert_equal Magic.new(8765, :arcane), Magic.parse(" 8765 arcane ")
164
+ end
165
+
166
+ test ".parse raises with multiple periods in fractional numbers" do
167
+ exception = assert_raises(Measured::UnitError) do
168
+ Magic.parse("12.34.56 ice")
169
+ end
170
+ assert_equal "Cannot parse measurement from '12.34.56 ice'", exception.message
171
+ end
172
+
173
+ test ".parse parses negative numbers" do
174
+ assert_equal Magic.new(-12.34, :arcane), Magic.parse("-12.34 arcane")
175
+ end
176
+
177
+ test ".parse parses rational numbers" do
178
+ assert_equal Magic.new(1.5, :magic_missile), Magic.parse("3/2magic missile")
179
+ end
180
+
181
+ test ".parse raises on unknown unit" do
182
+ exception = assert_raises(Measured::UnitError) do
183
+ Magic.parse("1 fake")
184
+ end
185
+ assert_equal "Unit 'fake' does not exist", exception.message
186
+ end
187
+
118
188
  test "#convert_to raises on an invalid unit" do
119
189
  assert_raises Measured::UnitError do
120
190
  @magic.convert_to(Measured::Unit.new(:punch))
@@ -156,8 +226,8 @@ class Measured::MeasurableTest < ActiveSupport::TestCase
156
226
  end
157
227
 
158
228
  test "#inspect shows the number and the unit" do
159
- assert_equal "#<Magic: 10 #<Measured::CaseInsensitiveUnit: fireball (fire, fireballs) 2/3 magic_missile>>", Magic.new(10, :fire).inspect
160
- assert_equal "#<Magic: 1.234 #<Measured::CaseInsensitiveUnit: magic_missile (magic_missiles)>>", Magic.new(1.234, :magic_missile).inspect
229
+ assert_equal "#<Magic: 10 #<Measured::Unit: fireball (fire, fireballs) 2/3 magic_missile>>", Magic.new(10, :fire).inspect
230
+ assert_equal "#<Magic: 1.234 #<Measured::Unit: magic_missile (magic_missiles, magic missile)>>", Magic.new(1.234, :magic_missile).inspect
161
231
  end
162
232
 
163
233
  test "#zero? always returns false" do
@@ -215,5 +285,4 @@ class Measured::MeasurableTest < ActiveSupport::TestCase
215
285
  assert_raises(ArgumentError) { @magic < BigDecimal.new(0) }
216
286
  assert_raises(ArgumentError) { @magic < 0.00 }
217
287
  end
218
-
219
288
  end
@@ -0,0 +1,88 @@
1
+ require "test_helper"
2
+
3
+ class Measured::ParserTest < ActiveSupport::TestCase
4
+ test "#parse raises on nil input" do
5
+ exception = assert_raises(Measured::UnitError) do
6
+ Measured::Parser.parse_string(nil)
7
+ end
8
+ assert_equal "Cannot parse blank measurement", exception.message
9
+ end
10
+
11
+ test "#parse raises on blank string input" do
12
+ exception = assert_raises(Measured::UnitError) do
13
+ Measured::Parser.parse_string("")
14
+ end
15
+ assert_equal "Cannot parse blank measurement", exception.message
16
+ end
17
+
18
+ test "#parse raises on a single incorrect string" do
19
+ exception = assert_raises(Measured::UnitError) do
20
+ Measured::Parser.parse_string("word")
21
+ end
22
+ assert_equal "Cannot parse measurement from 'word'", exception.message
23
+ end
24
+
25
+ test "#parse raises on a single incorrect number" do
26
+ exception = assert_raises(Measured::UnitError) do
27
+ Measured::Parser.parse_string("1234")
28
+ end
29
+ assert_equal "Cannot parse measurement from '1234'", exception.message
30
+ end
31
+
32
+ test "#parse raises on a multiple incorrect numbers" do
33
+ exception = assert_raises(Measured::UnitError) do
34
+ Measured::Parser.parse_string("12.34 9999")
35
+ end
36
+ assert_equal "Cannot parse measurement from '12.34 9999'", exception.message
37
+ end
38
+
39
+ test "#parse takes input with a space between" do
40
+ assert_equal [Rational(2, 1), "test"], Measured::Parser.parse_string("4/2 test")
41
+ end
42
+
43
+ test "#parse takes input without a space" do
44
+ assert_equal [Rational(7, 2), "test"], Measured::Parser.parse_string("3.5test")
45
+ end
46
+
47
+ test "#parse takes input with a number in the unit" do
48
+ assert_equal [Rational(1, 1), "test3test"], Measured::Parser.parse_string("1 test3test")
49
+ end
50
+
51
+ test "#parse raises on a number first unit digit" do
52
+ exception = assert_raises(Measured::UnitError) do
53
+ Measured::Parser.parse_string("1 1test")
54
+ end
55
+ assert_equal "Cannot parse measurement from '1 1test'", exception.message
56
+ end
57
+
58
+ test "#parse takes float with a space" do
59
+ assert_equal [Rational(5, 4), "test"], Measured::Parser.parse_string("1.25 test")
60
+ end
61
+
62
+ test "#parse takes float without a space" do
63
+ assert_equal [Rational(251, 5), "test"], Measured::Parser.parse_string("50.2test")
64
+ end
65
+
66
+ test "#parse truncates any space before and after" do
67
+ assert_equal [Rational(111111, 100), "test"], Measured::Parser.parse_string(" 1111.11 test ")
68
+ end
69
+
70
+ test "#parse raises with multiple periods in fractional numbers" do
71
+ exception = assert_raises(Measured::UnitError) do
72
+ Measured::Parser.parse_string("12.34.56 test")
73
+ end
74
+ assert_equal "Cannot parse measurement from '12.34.56 test'", exception.message
75
+ end
76
+
77
+ test "#parse takes multiple words for the unit" do
78
+ assert_equal [Rational(2345, 1), "a b cde"], Measured::Parser.parse_string(" 2345 a b cde ")
79
+ end
80
+
81
+ test "#parse parses negative numbers" do
82
+ assert_equal [Rational(-13, 4), "test"], Measured::Parser.parse_string("-3.25 test")
83
+ end
84
+
85
+ test "#parse parses rational numbers" do
86
+ assert_equal [Rational(3, 2), "test"], Measured::Parser.parse_string("3/2test")
87
+ end
88
+ end
@@ -1,13 +1,5 @@
1
1
  Magic = Measured.build do
2
- unit :magic_missile, aliases: [:magic_missiles]
3
- unit :fireball, value: "2/3 magic_missile", aliases: [:fire, :fireballs]
4
- unit :ice, value: "2 magic_missile"
5
- unit :arcane, value: "10 magic_missile"
6
- unit :ultima, value: "10 arcane"
7
- end
8
-
9
- CaseSensitiveMagic = Measured.build(case_sensitive: true) do
10
- unit :magic_missile, aliases: [:magic_missiles]
2
+ unit :magic_missile, aliases: [:magic_missiles, "magic missile"]
11
3
  unit :fireball, value: "2/3 magic_missile", aliases: [:fire, :fireballs]
12
4
  unit :ice, value: "2 magic_missile"
13
5
  unit :arcane, value: "10 magic_missile"
@@ -1,10 +1,13 @@
1
1
  require "measured"
2
+ require "minitest/reporters"
2
3
  require "minitest/autorun"
3
4
  require "mocha/setup"
4
5
  require "pry"
5
6
 
6
7
  ActiveSupport.test_order = :random
7
8
 
9
+ Minitest::Reporters.use! [Minitest::Reporters::ProgressReporter.new(color: true)]
10
+
8
11
  require "support/fake_system"
9
12
 
10
13
  class ActiveSupport::TestCase
@@ -20,24 +20,16 @@ class Measured::UnitSystemBuilderTest < ActiveSupport::TestCase
20
20
  end
21
21
 
22
22
  assert_raises Measured::UnitError do
23
- Measured.build(case_sensitive: true) do
23
+ Measured.build do
24
24
  unit :m
25
25
  unit :in, aliases: [:inch], value: "0.0254 m"
26
26
  unit :inch, aliases: [:thing], value: "123 m"
27
27
  end
28
28
  end
29
-
30
- assert_raises Measured::UnitError do
31
- Measured.build(case_sensitive: false) do
32
- unit :normal
33
- unit :bold, aliases: [:strong], value: "10 normal"
34
- unit :bolder, aliases: [:BOLD], value: "100 normal"
35
- end
36
- end
37
29
  end
38
30
 
39
- test "#case_sensitive true produces a case-sensitive conversion" do
40
- measurable = Measured.build(case_sensitive: true) do
31
+ test "#unit is case sensitive" do
32
+ measurable = Measured.build do
41
33
  unit :normal
42
34
  unit :bold, value: "10 normal"
43
35
  unit :BOLD, value: "100 normal"
@@ -45,14 +37,4 @@ class Measured::UnitSystemBuilderTest < ActiveSupport::TestCase
45
37
 
46
38
  assert_equal 'BOLD', measurable.unit_system.unit_for!(:BOLD).name
47
39
  end
48
-
49
- test "case-insensitive conversion is produced by default" do
50
- measurable = Measured.build(case_sensitive: false) do
51
- unit :normal
52
- unit :bold, value: "10 normal"
53
- unit :bolder, value: "100 normal"
54
- end
55
-
56
- assert_equal 'bold', measurable.unit_system.unit_for!(:bOlD).name
57
- end
58
40
  end
@@ -2,7 +2,7 @@ require "test_helper"
2
2
 
3
3
  class Measured::UnitSystemTest < ActiveSupport::TestCase
4
4
  setup do
5
- @unit_fireball = CaseSensitiveMagic.unit_system.unit_for!(:fireball)
5
+ @unit_fireball = Magic.unit_system.unit_for!(:fireball)
6
6
 
7
7
  @unit_m = Measured::Unit.new(:m)
8
8
  @unit_in = Measured::Unit.new(:in, aliases: [:Inch], value: "0.0254 m")
@@ -46,36 +46,36 @@ class Measured::UnitSystemTest < ActiveSupport::TestCase
46
46
  end
47
47
 
48
48
  test "#unit_for converts a unit name to its base unit" do
49
- assert_equal @unit_fireball, CaseSensitiveMagic.unit_system.unit_for("fire")
49
+ assert_equal @unit_fireball, Magic.unit_system.unit_for("fire")
50
50
  end
51
51
 
52
52
  test "#unit_for does not care about string or symbol" do
53
- assert_equal @unit_fireball, CaseSensitiveMagic.unit_system.unit_for(:fire)
53
+ assert_equal @unit_fireball, Magic.unit_system.unit_for(:fire)
54
54
  end
55
55
 
56
56
  test "#unit_for passes through if already base unit name" do
57
- assert_equal @unit_fireball, CaseSensitiveMagic.unit_system.unit_for("fireball")
57
+ assert_equal @unit_fireball, Magic.unit_system.unit_for("fireball")
58
58
  end
59
59
 
60
60
  test "#unit_for returns nil if not found" do
61
- assert_nil CaseSensitiveMagic.unit_system.unit_for("thunder")
61
+ assert_nil Magic.unit_system.unit_for("thunder")
62
62
  end
63
63
 
64
64
  test "#unit_for! converts a unit name to its base unit" do
65
- assert_equal @unit_fireball, CaseSensitiveMagic.unit_system.unit_for!("fire")
65
+ assert_equal @unit_fireball, Magic.unit_system.unit_for!("fire")
66
66
  end
67
67
 
68
68
  test "#unit_for! does not care about string or symbol" do
69
- assert_equal @unit_fireball, CaseSensitiveMagic.unit_system.unit_for!(:fire)
69
+ assert_equal @unit_fireball, Magic.unit_system.unit_for!(:fire)
70
70
  end
71
71
 
72
72
  test "#unit_for! passes through if already base unit name" do
73
- assert_equal @unit_fireball, CaseSensitiveMagic.unit_system.unit_for!("fireball")
73
+ assert_equal @unit_fireball, Magic.unit_system.unit_for!("fireball")
74
74
  end
75
75
 
76
76
  test "#unit_for! raises if not found" do
77
77
  assert_raises_with_message(Measured::UnitError, "Unit 'thunder' does not exist") do
78
- CaseSensitiveMagic.unit_system.unit_for!("thunder")
78
+ Magic.unit_system.unit_for!("thunder")
79
79
  end
80
80
  end
81
81
 
@@ -83,11 +83,11 @@ class Measured::UnitSystemTest < ActiveSupport::TestCase
83
83
  unit_bad = Measured::Unit.new(:doesnt_exist)
84
84
 
85
85
  assert_raises Measured::UnitError do
86
- CaseSensitiveMagic.unit_system.convert(1, from: @unit_fireball, to: unit_bad)
86
+ Magic.unit_system.convert(1, from: @unit_fireball, to: unit_bad)
87
87
  end
88
88
 
89
89
  assert_raises Measured::UnitError do
90
- CaseSensitiveMagic.unit_system.convert(1, from: unit_bad, to: @unit_fireball)
90
+ Magic.unit_system.convert(1, from: unit_bad, to: @unit_fireball)
91
91
  end
92
92
  end
93
93
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: measured
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre3
4
+ version: 2.0.0.pre4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin McPhillips
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-01 00:00:00.000000000 Z
11
+ date: 2017-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -28,42 +28,56 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.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: '10.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 5.5.1
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 5.5.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest-reporters
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: mocha
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - "~>"
73
+ - - ">"
60
74
  - !ruby/object:Gem::Version
61
75
  version: 1.1.0
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - "~>"
80
+ - - ">"
67
81
  - !ruby/object:Gem::Version
68
82
  version: 1.1.0
69
83
  - !ruby/object:Gem::Dependency
@@ -99,10 +113,9 @@ files:
99
113
  - lib/measured.rb
100
114
  - lib/measured/arithmetic.rb
101
115
  - lib/measured/base.rb
102
- - lib/measured/case_insensitive_unit.rb
103
- - lib/measured/case_insensitive_unit_system.rb
104
116
  - lib/measured/conversion_table.rb
105
117
  - lib/measured/measurable.rb
118
+ - lib/measured/parser.rb
106
119
  - lib/measured/unit.rb
107
120
  - lib/measured/unit_system.rb
108
121
  - lib/measured/unit_system_builder.rb
@@ -112,10 +125,9 @@ files:
112
125
  - measured.gemspec
113
126
  - shipit.rubygems.yml
114
127
  - test/arithmetic_test.rb
115
- - test/case_insensitive_unit_system_test.rb
116
- - test/case_insensitive_unit_test.rb
117
128
  - test/conversion_table_test.rb
118
129
  - test/measurable_test.rb
130
+ - test/parser_test.rb
119
131
  - test/support/fake_system.rb
120
132
  - test/test_helper.rb
121
133
  - test/unit_error_test.rb
@@ -144,16 +156,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
156
  version: 1.3.1
145
157
  requirements: []
146
158
  rubyforge_project:
147
- rubygems_version: 2.5.1
159
+ rubygems_version: 2.5.2
148
160
  signing_key:
149
161
  specification_version: 4
150
162
  summary: Encapsulate measurements with their units in Ruby
151
163
  test_files:
152
164
  - test/arithmetic_test.rb
153
- - test/case_insensitive_unit_system_test.rb
154
- - test/case_insensitive_unit_test.rb
155
165
  - test/conversion_table_test.rb
156
166
  - test/measurable_test.rb
167
+ - test/parser_test.rb
157
168
  - test/support/fake_system.rb
158
169
  - test/test_helper.rb
159
170
  - test/unit_error_test.rb
@@ -1,17 +0,0 @@
1
- class Measured::CaseInsensitiveUnit < Measured::Unit
2
- def initialize(name, aliases: [], value: nil, unit_system: nil)
3
- super(
4
- name.to_s.downcase,
5
- aliases: aliases.map(&:to_s).map!(&:downcase),
6
- value: value,
7
- unit_system: unit_system
8
- )
9
- end
10
-
11
- private
12
-
13
- def parse_value(tokens)
14
- value, unit = super
15
- [value, unit.downcase]
16
- end
17
- end
@@ -1,9 +0,0 @@
1
- class Measured::CaseInsensitiveUnitSystem < Measured::UnitSystem
2
- def unit?(name)
3
- super(name.to_s.downcase)
4
- end
5
-
6
- def unit_for(name)
7
- unit_name_to_unit[name.to_s.downcase]
8
- end
9
- end
@@ -1,101 +0,0 @@
1
- require "test_helper"
2
-
3
- class Measured::CaseInsensitiveUnitSystemTest < ActiveSupport::TestCase
4
- setup do
5
- @unit_fireball = Magic.unit_system.unit_for!(:fireball)
6
-
7
- @unit_m = Measured::CaseInsensitiveUnit.new(:m)
8
- @unit_in = Measured::CaseInsensitiveUnit.new(:in, aliases: [:inch], value: "0.0254 m")
9
- @unit_ft = Measured::CaseInsensitiveUnit.new(:ft, aliases: %w(Feet FOOT), value: "0.3048 m")
10
- @conversion = Measured::CaseInsensitiveUnitSystem.new([@unit_m, @unit_in, @unit_ft])
11
- end
12
-
13
- test "#unit_names_with_aliases lists all allowed unit names in lowercase" do
14
- assert_equal %w(feet foot ft in inch m), @conversion.unit_names_with_aliases
15
- end
16
-
17
- test "#unit_names lists all base unit names without aliases in lowercase" do
18
- assert_equal %w(ft in m), @conversion.unit_names
19
- end
20
-
21
- test "#unit? checks if the unit is part of the units but not aliases" do
22
- assert @conversion.unit?(:in)
23
- assert @conversion.unit?("m")
24
- assert @conversion.unit?("M")
25
- refute @conversion.unit?("inch")
26
- refute @conversion.unit?(:yard)
27
- end
28
-
29
- test "#unit? with blank and nil arguments" do
30
- refute @conversion.unit?("")
31
- refute @conversion.unit?(nil)
32
- end
33
-
34
- test "#unit_or_alias? checks if the unit is part of the units or aliases" do
35
- assert @conversion.unit_or_alias?(:inch)
36
- assert @conversion.unit_or_alias?("m")
37
- assert @conversion.unit_or_alias?(:IN)
38
- assert @conversion.unit_or_alias?("in")
39
- refute @conversion.unit_or_alias?(:yard)
40
- end
41
-
42
- test "#unit_or_alias? with blank and nil arguments" do
43
- refute @conversion.unit_or_alias?("")
44
- refute @conversion.unit_or_alias?(nil)
45
- end
46
-
47
- test "#unit_for converts a unit name to its base unit" do
48
- assert_equal @unit_fireball, Magic.unit_system.unit_for("fire")
49
- end
50
-
51
- test "#unit_for does not care about string or symbol" do
52
- assert_equal @unit_fireball, Magic.unit_system.unit_for(:fire)
53
- end
54
-
55
- test "#unit_for passes through if already base unit name" do
56
- assert_equal @unit_fireball, Magic.unit_system.unit_for("fireball")
57
- end
58
-
59
- test "#unit_for returns nil if not found" do
60
- assert_nil Magic.unit_system.unit_for("thunder")
61
- end
62
-
63
- test "#unit_for! converts a unit name to its base unit" do
64
- assert_equal @unit_fireball, Magic.unit_system.unit_for!("fire")
65
- end
66
-
67
- test "#unit_for! does not care about string or symbol" do
68
- assert_equal @unit_fireball, Magic.unit_system.unit_for!(:fire)
69
- end
70
-
71
- test "#unit_for! passes through if already base unit name" do
72
- assert_equal @unit_fireball, Magic.unit_system.unit_for!("fireball")
73
- end
74
-
75
- test "#unit_for! raises if not found" do
76
- assert_raises_with_message(Measured::UnitError, "Unit 'thunder' does not exist") do
77
- Magic.unit_system.unit_for!("thunder")
78
- end
79
- end
80
-
81
- test "#convert raises if either unit is not found" do
82
- unit_bad = Measured::Unit.new(:doesnt_exist)
83
-
84
- assert_raises Measured::UnitError do
85
- Magic.unit_system.convert(1, from: @unit_fireball, to: unit_bad)
86
- end
87
-
88
- assert_raises Measured::UnitError do
89
- Magic.unit_system.convert(1, from: unit_bad, to: @unit_fireball)
90
- end
91
- end
92
-
93
- test "#convert converts between two known units" do
94
- assert_equal 3, @conversion.convert(36, from: @unit_in, to: @unit_ft)
95
- assert_equal 18, @conversion.convert(Rational(3, 2), from: @unit_ft, to: @unit_in)
96
- end
97
-
98
- test "#convert handles the same unit" do
99
- assert_equal 2, @conversion.convert(2, from: @unit_in, to: @unit_in)
100
- end
101
- end
@@ -1,81 +0,0 @@
1
- require "test_helper"
2
-
3
- class Measured::CaseInsensitiveUnitTest < ActiveSupport::TestCase
4
- setup do
5
- @unit = Measured::CaseInsensitiveUnit.new(:Pie, value: "10 Cake")
6
- @unit_with_aliases = Measured::CaseInsensitiveUnit.new(:Pie, aliases: %w(Cake Tart))
7
- end
8
-
9
- test "#initialize converts the name to a downcased string" do
10
- assert_equal "pie", @unit.name
11
- end
12
-
13
- test "#initialize converts aliases to strings and makes a list of sorted, downcased names" do
14
- assert_equal %w(cake pie sweets), Measured::CaseInsensitiveUnit.new(:pie, aliases: ["Cake", :Sweets]).names
15
- end
16
-
17
- test "#initialize parses out the unit and the number part" do
18
- assert_equal 10, @unit.conversion_amount
19
- assert_equal "cake", @unit.conversion_unit
20
-
21
- unit = Measured::CaseInsensitiveUnit.new(:pie, value: "5.5 sweets")
22
- assert_equal BigDecimal("5.5"), unit.conversion_amount
23
- assert_equal "sweets", unit.conversion_unit
24
-
25
- unit = Measured::CaseInsensitiveUnit.new(:pie, value: "1/3 Bitter Pies")
26
- assert_equal Rational(1, 3), unit.conversion_amount
27
- assert_equal "bitter pies", unit.conversion_unit
28
- end
29
-
30
- test "#initialize raises if the format of the value is incorrect" do
31
- assert_raises Measured::UnitError do
32
- Measured::CaseInsensitiveUnit.new(:pie, value: "hello")
33
- end
34
-
35
- assert_raises Measured::UnitError do
36
- Measured::CaseInsensitiveUnit.new(:pie, value: "123456")
37
- end
38
- end
39
-
40
- test "#to_s returns an expected string" do
41
- assert_equal "pie", Measured::CaseInsensitiveUnit.new(:pie).to_s
42
- assert_equal "pie (1/2 sweet)", Measured::CaseInsensitiveUnit.new(:pie, aliases: ["cake"], value: "0.5 sweet").to_s
43
- end
44
-
45
- test "#inspect returns an expected string" do
46
- assert_equal "#<Measured::CaseInsensitiveUnit: pie>", Measured::CaseInsensitiveUnit.new(:pie).inspect
47
- assert_equal "#<Measured::CaseInsensitiveUnit: pie (cake)>", Measured::CaseInsensitiveUnit.new(:pie, aliases: ["CAKE"]).inspect
48
- assert_equal "#<Measured::CaseInsensitiveUnit: pie 1/2 sweet>", Measured::CaseInsensitiveUnit.new(:Pie, value: "1/2 sweet").inspect
49
- assert_equal "#<Measured::CaseInsensitiveUnit: pie (cake) 1/2 sweet>", Measured::CaseInsensitiveUnit.new(:pie, aliases: ["cake"], value: "1/2 sweet").inspect
50
- end
51
-
52
- test "includes Comparable mixin" do
53
- assert Measured::Unit.ancestors.include?(Comparable)
54
- end
55
-
56
- test "#<=> compares non-Unit classes against name" do
57
- assert_equal 1, @unit <=> "pap"
58
- assert_equal -1, @unit <=> "pop"
59
- end
60
-
61
- test "#<=> is 0 for Unit instances that should be equivalent" do
62
- assert_equal 0, @unit <=> Measured::CaseInsensitiveUnit.new(:Pie, value: "10 cake")
63
- assert_equal 0, @unit <=> Measured::CaseInsensitiveUnit.new("Pie", value: "10 cake")
64
- assert_equal 0, @unit <=> Measured::CaseInsensitiveUnit.new("Pie", value: [10, :cake])
65
- end
66
-
67
- test "#<=> is 1 for units with names that come after Pie lexicographically" do
68
- assert_equal 1, @unit <=> Measured::CaseInsensitiveUnit.new(:pancake, value: "10 cake")
69
- assert_equal 1, @unit <=> Measured::CaseInsensitiveUnit.new("pie", aliases: ["pancakes"], value: "10 cake")
70
- end
71
-
72
- test "#<=> compares #conversion_amount when unit names the same" do
73
- assert_equal -1, @unit <=> Measured::CaseInsensitiveUnit.new(:pie, value: [11, :pancake])
74
- assert_equal 0, @unit <=> Measured::CaseInsensitiveUnit.new(:pie, value: [10, :foo])
75
- assert_equal 1, @unit <=> Measured::CaseInsensitiveUnit.new(:pie, value: [9, :pancake])
76
- end
77
-
78
- test "#inverse_conversion_amount returns 1/amount" do
79
- assert_equal Rational(1, 10), @unit.inverse_conversion_amount
80
- end
81
- end