measured 2.3.0 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
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