measured 2.0.0.pre3 → 2.0.0.pre4

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