measured 2.3.0 → 2.6.0

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.
Files changed (56) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +31 -0
  3. data/CHANGELOG.md +25 -0
  4. data/README.md +12 -10
  5. data/Rakefile +22 -1
  6. data/cache/.keep +0 -0
  7. data/cache/length.json +2553 -0
  8. data/cache/volume.json +4163 -0
  9. data/cache/weight.json +3195 -0
  10. data/dev.yml +2 -2
  11. data/gemfiles/{activesupport-4.2.gemfile → activesupport-5.2.gemfile} +1 -1
  12. data/gemfiles/activesupport-6.0.gemfile +5 -0
  13. data/gemfiles/activesupport-6.1.gemfile +5 -0
  14. data/lib/measured.rb +1 -0
  15. data/lib/measured/arithmetic.rb +1 -0
  16. data/lib/measured/base.rb +12 -6
  17. data/lib/measured/cache/json.rb +49 -0
  18. data/lib/measured/cache/json_writer.rb +9 -0
  19. data/lib/measured/cache/null.rb +16 -0
  20. data/lib/measured/conversion_table_builder.rb +91 -0
  21. data/lib/measured/measurable.rb +18 -21
  22. data/lib/measured/missing_conversion_path.rb +12 -0
  23. data/lib/measured/parser.rb +1 -0
  24. data/lib/measured/unit.rb +16 -26
  25. data/lib/measured/unit_already_added.rb +11 -0
  26. data/lib/measured/unit_error.rb +4 -0
  27. data/lib/measured/unit_system.rb +26 -21
  28. data/lib/measured/unit_system_builder.rb +11 -4
  29. data/lib/measured/units/length.rb +3 -0
  30. data/lib/measured/units/volume.rb +4 -1
  31. data/lib/measured/units/weight.rb +3 -0
  32. data/lib/measured/version.rb +2 -1
  33. data/measured.gemspec +13 -5
  34. data/test/arithmetic_test.rb +1 -0
  35. data/test/cache/json_test.rb +43 -0
  36. data/test/cache/json_writer_test.rb +23 -0
  37. data/test/cache/null_test.rb +20 -0
  38. data/test/cache_consistency_test.rb +19 -0
  39. data/test/conversion_table_builder_test.rb +137 -0
  40. data/test/measurable_test.rb +5 -5
  41. data/test/parser_test.rb +1 -0
  42. data/test/support/always_true_cache.rb +14 -0
  43. data/test/support/fake_system.rb +1 -0
  44. data/test/support/subclasses.rb +7 -0
  45. data/test/test_helper.rb +5 -3
  46. data/test/unit_error_test.rb +1 -0
  47. data/test/unit_system_builder_test.rb +49 -3
  48. data/test/unit_system_test.rb +15 -0
  49. data/test/unit_test.rb +5 -0
  50. data/test/units/length_test.rb +5 -4
  51. data/test/units/volume_test.rb +6 -5
  52. data/test/units/weight_test.rb +1 -0
  53. metadata +45 -18
  54. data/.travis.yml +0 -17
  55. data/lib/measured/conversion_table.rb +0 -65
  56. data/test/conversion_table_test.rb +0 -98
@@ -1,17 +1,19 @@
1
+ # frozen_string_literal: true
2
+ require "pry" unless ENV["CI"]
1
3
  require "measured"
2
4
  require "minitest/reporters"
3
5
  require "minitest/autorun"
4
- require "mocha/setup"
5
- require "pry"
6
+ require "mocha/minitest"
6
7
 
7
8
  ActiveSupport.test_order = :random
8
9
 
9
10
  Minitest::Reporters.use! [Minitest::Reporters::ProgressReporter.new(color: true)]
10
11
 
12
+ require "support/subclasses"
11
13
  require "support/fake_system"
14
+ require "support/always_true_cache"
12
15
 
13
16
  class ActiveSupport::TestCase
14
-
15
17
  protected
16
18
 
17
19
  def assert_close_bigdecimal exp, act, delta = BigDecimal('0.000001')
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::UnitErrorTest < ActiveSupport::TestCase
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::UnitSystemBuilderTest < ActiveSupport::TestCase
@@ -11,15 +12,17 @@ class Measured::UnitSystemBuilderTest < ActiveSupport::TestCase
11
12
  end
12
13
 
13
14
  test "#unit cannot add duplicate unit names" do
14
- assert_raises Measured::UnitError do
15
+ error = assert_raises Measured::UnitAlreadyAdded do
15
16
  Measured.build do
16
17
  unit :m
17
18
  unit :in, aliases: [:inch], value: "0.0254 m"
18
19
  unit :in, aliases: [:thing], value: "123 m"
19
20
  end
20
21
  end
22
+ assert_equal("in", error.unit_name)
23
+ assert_equal("Unit in has already been added.", error.message)
21
24
 
22
- assert_raises Measured::UnitError do
25
+ assert_raises Measured::UnitAlreadyAdded do
23
26
  Measured.build do
24
27
  unit :m
25
28
  unit :in, aliases: [:inch], value: "0.0254 m"
@@ -28,6 +31,19 @@ class Measured::UnitSystemBuilderTest < ActiveSupport::TestCase
28
31
  end
29
32
  end
30
33
 
34
+ test "#unit raises when cannot find conversion path" do
35
+ error = assert_raises Measured::MissingConversionPath do
36
+ Measured.build do
37
+ unit :m
38
+ unit :in, value: "0.0254 m"
39
+ unit :pallets, value: "5 cases"
40
+ end
41
+ end
42
+ assert_equal("pallets", error.from)
43
+ assert_equal("m", error.to)
44
+ assert_equal("Cannot find conversion path from pallets to m.", error.message)
45
+ end
46
+
31
47
  test "#unit is case sensitive" do
32
48
  measurable = Measured.build do
33
49
  unit :normal
@@ -38,6 +54,16 @@ class Measured::UnitSystemBuilderTest < ActiveSupport::TestCase
38
54
  assert_equal 'BOLD', measurable.unit_system.unit_for!(:BOLD).name
39
55
  end
40
56
 
57
+ test "#unit traverses aliases" do
58
+ measurable = Measured.build do
59
+ unit :piece, aliases: [:pieces]
60
+ unit :dozen, aliases: [:dz], value: "12 pieces"
61
+ end
62
+
63
+ assert_equal 12, measurable.unit_system.units.last.conversion_amount
64
+ assert_equal "piece", measurable.unit_system.units.last.conversion_unit
65
+ end
66
+
41
67
  test "#si_unit adds 21 new units" do
42
68
  measurable = Measured.build do
43
69
  unit :ft
@@ -54,7 +80,7 @@ class Measured::UnitSystemBuilderTest < ActiveSupport::TestCase
54
80
  end
55
81
 
56
82
  prefixes = Measured::UnitSystemBuilder::SI_PREFIXES.map { |short, _, _| "#{short}ft" }
57
- prefixes += %w(in ft)
83
+ prefixes += %w(in ft)
58
84
  assert_equal prefixes.sort, measurable.unit_names
59
85
  end
60
86
 
@@ -109,4 +135,24 @@ class Measured::UnitSystemBuilderTest < ActiveSupport::TestCase
109
135
  assert_equal (2240), measurable.unit_system.unit_for!(:long_ton).conversion_amount
110
136
  assert_equal "lb", measurable.unit_system.unit_for!(:long_ton).conversion_unit
111
137
  end
138
+
139
+ test "#cache sets no cache by default" do
140
+ measurable = Measured.build do
141
+ unit :m
142
+ unit :km, value: "1000 m"
143
+ end
144
+
145
+ refute_predicate measurable.unit_system, :cached?
146
+ end
147
+
148
+ test "#cache sets the class and args" do
149
+ measurable = Measured.build do
150
+ unit :m
151
+ unit :km, value: "1000 m"
152
+
153
+ cache AlwaysTrueCache
154
+ end
155
+
156
+ assert_predicate measurable.unit_system, :cached?
157
+ end
112
158
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::UnitSystemTest < ActiveSupport::TestCase
@@ -99,4 +100,18 @@ class Measured::UnitSystemTest < ActiveSupport::TestCase
99
100
  test "#convert handles the same unit" do
100
101
  assert_equal 2, @conversion.convert(2, from: @unit_in, to: @unit_in)
101
102
  end
103
+
104
+ test "#update_cache calls the builder" do
105
+ Measured::ConversionTableBuilder.any_instance.expects(:update_cache)
106
+ @conversion.update_cache
107
+ end
108
+
109
+ test "#cached? calls the builder and is false" do
110
+ refute_predicate @conversion, :cached?
111
+ end
112
+
113
+ test "#cached? calls the builder and is true" do
114
+ conversion = Measured::UnitSystem.new([@unit_m, @unit_in, @unit_ft], cache: { class: AlwaysTrueCache })
115
+ assert_predicate conversion, :cached?
116
+ end
102
117
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::UnitTest < ActiveSupport::TestCase
@@ -78,4 +79,8 @@ class Measured::UnitTest < ActiveSupport::TestCase
78
79
  test "#inverse_conversion_amount returns 1/amount" do
79
80
  assert_equal Rational(1, 10), @unit.inverse_conversion_amount
80
81
  end
82
+
83
+ test "#inverse_conversion_amount handles nil for base unit" do
84
+ assert_nil Measured::Unit.new(:pie).inverse_conversion_amount
85
+ end
81
86
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::LengthTest < ActiveSupport::TestCase
@@ -142,7 +143,7 @@ class Measured::LengthTest < ActiveSupport::TestCase
142
143
  end
143
144
 
144
145
  test ".convert_to from km to mi" do
145
- assert_conversion Measured::Length, "2000 km", "0.1242742384475E4 mi"
146
+ assert_conversion Measured::Length, "2000 km", "0.1242742384475E4 mi"
146
147
  end
147
148
 
148
149
  test ".convert_to from km to mm" do
@@ -150,7 +151,7 @@ class Measured::LengthTest < ActiveSupport::TestCase
150
151
  end
151
152
 
152
153
  test ".convert_to from km to yd" do
153
- assert_conversion Measured::Length, "2000 km", "0.218722659667542E7 yd"
154
+ assert_conversion Measured::Length, "2000 km", "0.218722659667542E7 yd"
154
155
  end
155
156
 
156
157
  test ".convert_to from m to cm" do
@@ -206,7 +207,7 @@ class Measured::LengthTest < ActiveSupport::TestCase
206
207
  end
207
208
 
208
209
  test ".convert_to from mi to mi" do
209
- assert_exact_conversion Measured::Length, "2000 mi", "2000 mi"
210
+ assert_exact_conversion Measured::Length, "2000 mi", "2000 mi"
210
211
  end
211
212
 
212
213
  test ".convert_to from mi to mm" do
@@ -214,7 +215,7 @@ class Measured::LengthTest < ActiveSupport::TestCase
214
215
  end
215
216
 
216
217
  test ".convert_to from mi to yd" do
217
- assert_exact_conversion Measured::Length, "2000 mi", "3520000 yd"
218
+ assert_exact_conversion Measured::Length, "2000 mi", "3520000 yd"
218
219
  end
219
220
 
220
221
  test ".convert_to from mm to cm" do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::VolumeTest < ActiveSupport::TestCase
@@ -68,7 +69,7 @@ class Measured::VolumeTest < ActiveSupport::TestCase
68
69
  test ".unit_names should be the list of base unit names" do
69
70
  expected_units = %w(l m3 ft3 in3 gal us_gal qt us_qt pt us_pt oz us_oz)
70
71
  expected_units += Measured::UnitSystemBuilder::SI_PREFIXES.map { |short, _, _| "#{short}l" }
71
- assert_equal expected_units.sort, Measured::Volume.unit_names
72
+ assert_equal expected_units.sort, Measured::Volume.unit_names
72
73
  end
73
74
 
74
75
  test ".name" do
@@ -95,7 +96,7 @@ class Measured::VolumeTest < ActiveSupport::TestCase
95
96
  test ".convert_to from gal to gal" do
96
97
  assert_conversion Measured::Volume, "2000 gal", "2000 gal"
97
98
  end
98
-
99
+
99
100
  test ".convert_to from us_gal to us_gal" do
100
101
  assert_conversion Measured::Volume, "2000 us_gal", "2000 us_gal"
101
102
  end
@@ -123,7 +124,7 @@ class Measured::VolumeTest < ActiveSupport::TestCase
123
124
  test ".convert_to from us_oz to us_oz" do
124
125
  assert_conversion Measured::Volume, "2000 us_oz", "2000 us_oz"
125
126
  end
126
-
127
+
127
128
  test ".convert_to from ml to m3" do
128
129
  assert_conversion Measured::Volume, "2000 ml", "0.002 m3"
129
130
  end
@@ -303,7 +304,7 @@ class Measured::VolumeTest < ActiveSupport::TestCase
303
304
  test ".convert_to from gal to us_oz" do
304
305
  assert_conversion Measured::Volume, "2 gal", "307.4431809292 us_oz"
305
306
  end
306
-
307
+
307
308
  test ".convert_to from us_gal to qt" do
308
309
  assert_conversion Measured::Volume, "2 us_gal", "6.661393477 qt"
309
310
  end
@@ -387,4 +388,4 @@ class Measured::VolumeTest < ActiveSupport::TestCase
387
388
  test ".convert_to from oz to us_oz" do
388
389
  assert_conversion Measured::Volume, "2 oz", "1.9215207864 us_oz"
389
390
  end
390
- end
391
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::WeightTest < ActiveSupport::TestCase
metadata CHANGED
@@ -1,14 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: measured
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin McPhillips
8
+ - Jason Gedge
9
+ - Javier Honduvilla Coto
8
10
  autorequire:
9
11
  bindir: bin
10
12
  cert_chain: []
11
- date: 2018-01-17 00:00:00.000000000 Z
13
+ date: 2020-12-10 00:00:00.000000000 Z
12
14
  dependencies:
13
15
  - !ruby/object:Gem::Dependency
14
16
  name: activesupport
@@ -16,14 +18,14 @@ dependencies:
16
18
  requirements:
17
19
  - - ">="
18
20
  - !ruby/object:Gem::Version
19
- version: '4.2'
21
+ version: '5.2'
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
23
25
  requirements:
24
26
  - - ">="
25
27
  - !ruby/object:Gem::Version
26
- version: '4.2'
28
+ version: '5.2'
27
29
  - !ruby/object:Gem::Dependency
28
30
  name: rake
29
31
  requirement: !ruby/object:Gem::Requirement
@@ -70,16 +72,16 @@ dependencies:
70
72
  name: mocha
71
73
  requirement: !ruby/object:Gem::Requirement
72
74
  requirements:
73
- - - ">"
75
+ - - ">="
74
76
  - !ruby/object:Gem::Version
75
- version: 1.1.0
77
+ version: 1.4.0
76
78
  type: :development
77
79
  prerelease: false
78
80
  version_requirements: !ruby/object:Gem::Requirement
79
81
  requirements:
80
- - - ">"
82
+ - - ">="
81
83
  - !ruby/object:Gem::Version
82
- version: 1.1.0
84
+ version: 1.4.0
83
85
  - !ruby/object:Gem::Dependency
84
86
  name: pry
85
87
  requirement: !ruby/object:Gem::Requirement
@@ -94,29 +96,42 @@ dependencies:
94
96
  - - ">="
95
97
  - !ruby/object:Gem::Version
96
98
  version: '0'
97
- description: Wrapper objects which encapsulate measurments and their associated units
99
+ description: Wrapper objects which encapsulate measurements and their associated units
98
100
  in Ruby.
99
101
  email:
100
- - github@kevinmcphillips.ca
102
+ - gems@shopify.com
101
103
  executables: []
102
104
  extensions: []
103
105
  extra_rdoc_files: []
104
106
  files:
107
+ - ".github/workflows/ci.yml"
105
108
  - ".gitignore"
106
- - ".travis.yml"
109
+ - CHANGELOG.md
107
110
  - Gemfile
108
111
  - LICENSE
109
112
  - README.md
110
113
  - Rakefile
114
+ - cache/.keep
115
+ - cache/length.json
116
+ - cache/volume.json
117
+ - cache/weight.json
111
118
  - dev.yml
112
- - gemfiles/activesupport-4.2.gemfile
119
+ - gemfiles/activesupport-5.2.gemfile
120
+ - gemfiles/activesupport-6.0.gemfile
121
+ - gemfiles/activesupport-6.1.gemfile
113
122
  - lib/measured.rb
114
123
  - lib/measured/arithmetic.rb
115
124
  - lib/measured/base.rb
116
- - lib/measured/conversion_table.rb
125
+ - lib/measured/cache/json.rb
126
+ - lib/measured/cache/json_writer.rb
127
+ - lib/measured/cache/null.rb
128
+ - lib/measured/conversion_table_builder.rb
117
129
  - lib/measured/measurable.rb
130
+ - lib/measured/missing_conversion_path.rb
118
131
  - lib/measured/parser.rb
119
132
  - lib/measured/unit.rb
133
+ - lib/measured/unit_already_added.rb
134
+ - lib/measured/unit_error.rb
120
135
  - lib/measured/unit_system.rb
121
136
  - lib/measured/unit_system_builder.rb
122
137
  - lib/measured/units/length.rb
@@ -126,10 +141,16 @@ files:
126
141
  - measured.gemspec
127
142
  - shipit.rubygems.yml
128
143
  - test/arithmetic_test.rb
129
- - test/conversion_table_test.rb
144
+ - test/cache/json_test.rb
145
+ - test/cache/json_writer_test.rb
146
+ - test/cache/null_test.rb
147
+ - test/cache_consistency_test.rb
148
+ - test/conversion_table_builder_test.rb
130
149
  - test/measurable_test.rb
131
150
  - test/parser_test.rb
151
+ - test/support/always_true_cache.rb
132
152
  - test/support/fake_system.rb
153
+ - test/support/subclasses.rb
133
154
  - test/test_helper.rb
134
155
  - test/unit_error_test.rb
135
156
  - test/unit_system_builder_test.rb
@@ -141,7 +162,8 @@ files:
141
162
  homepage: https://github.com/Shopify/measured
142
163
  licenses:
143
164
  - MIT
144
- metadata: {}
165
+ metadata:
166
+ allowed_push_host: https://rubygems.org
145
167
  post_install_message:
146
168
  rdoc_options: []
147
169
  require_paths:
@@ -157,17 +179,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
179
  - !ruby/object:Gem::Version
158
180
  version: '0'
159
181
  requirements: []
160
- rubyforge_project:
161
- rubygems_version: 2.6.14
182
+ rubygems_version: 3.0.3
162
183
  signing_key:
163
184
  specification_version: 4
164
185
  summary: Encapsulate measurements with their units in Ruby
165
186
  test_files:
166
187
  - test/arithmetic_test.rb
167
- - test/conversion_table_test.rb
188
+ - test/cache/json_test.rb
189
+ - test/cache/json_writer_test.rb
190
+ - test/cache/null_test.rb
191
+ - test/cache_consistency_test.rb
192
+ - test/conversion_table_builder_test.rb
168
193
  - test/measurable_test.rb
169
194
  - test/parser_test.rb
195
+ - test/support/always_true_cache.rb
170
196
  - test/support/fake_system.rb
197
+ - test/support/subclasses.rb
171
198
  - test/test_helper.rb
172
199
  - test/unit_error_test.rb
173
200
  - test/unit_system_builder_test.rb
@@ -1,17 +0,0 @@
1
- language: ruby
2
- sudo: false
3
- cache: bundler
4
- rvm:
5
- - 2.1.8
6
- - 2.2.4
7
- - 2.3.1
8
- - 2.4.0
9
- gemfile:
10
- - Gemfile
11
- - gemfiles/activesupport-4.2.gemfile
12
- matrix:
13
- exclude:
14
- - gemfile: Gemfile
15
- rvm: 2.1.8
16
- - gemfile: gemfiles/activesupport-4.2.gemfile
17
- rvm: 2.4.0
@@ -1,65 +0,0 @@
1
- module Measured::ConversionTable
2
- extend self
3
-
4
- def build(units)
5
- table = {}
6
-
7
- units.map{|u| u.name}.each do |to_unit|
8
- to_table = {to_unit => BigDecimal("1")}
9
-
10
- table.each do |from_unit, from_table|
11
- to_table[from_unit] = find_conversion(units, to: from_unit, from: to_unit)
12
- from_table[to_unit] = find_conversion(units, to: to_unit, from: from_unit)
13
- end
14
-
15
- table[to_unit] = to_table
16
- end
17
-
18
- table
19
- end
20
-
21
- private
22
-
23
- def find_conversion(units, to:, from:)
24
- conversion = find_direct_conversion(units, to: to, from: from) || find_tree_traversal_conversion(units, to: to, from: from)
25
-
26
- raise Measured::UnitError, "Cannot find conversion path from #{ from } to #{ to }." unless conversion
27
-
28
- conversion
29
- end
30
-
31
- def find_direct_conversion(units, to:, from:)
32
- units.each do |unit|
33
- return unit.conversion_amount if unit.name == from && unit.conversion_unit == to
34
- end
35
-
36
- units.each do |unit|
37
- return unit.inverse_conversion_amount if unit.name == to && unit.conversion_unit == from
38
- end
39
-
40
- nil
41
- end
42
-
43
- def find_tree_traversal_conversion(units, to:, from:)
44
- traverse(units, from: from, to: to, unit_names: units.map(&:name), amount: 1)
45
- end
46
-
47
- def traverse(units, from:, to:, unit_names:, amount:)
48
- unit_names = unit_names - [from]
49
-
50
- unit_names.each do |name|
51
- if conversion = find_direct_conversion(units, from: from, to: name)
52
- new_amount = amount * conversion
53
- if name == to
54
- return new_amount
55
- else
56
- result = traverse(units, from: name, to: to, unit_names: unit_names, amount: new_amount)
57
- return result if result
58
- end
59
- end
60
- end
61
-
62
- nil
63
- end
64
-
65
- end