measured 2.5.0 → 2.5.1

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
  SHA256:
3
- metadata.gz: 9cc64e96e1ca065fbd9bdbe43bc80d9ae99fb2ffc52ddcba131180e439bfa462
4
- data.tar.gz: d7bd0237fb1dfb6f9c38a86ae32f0cc0d499b547aca8a7b2ddcc531ba7daabd8
3
+ metadata.gz: ded401e32179325e80114d1a2c184a1c03599156b7e332291f6e3a114bc1c7fb
4
+ data.tar.gz: 680d3cf30b58647232717d4f82b5eb0120e4e95f04f8b771cf70540ee860de0e
5
5
  SHA512:
6
- metadata.gz: c017c759124694968bb8c283c5f6a5f33af3f25544d9fe9fa190dcaeac59ce7e0a708019158604219fa3b332f9f2f022fe44bfbfa963682a65e50f63f583f5ec
7
- data.tar.gz: 6096418c372b51a8229148618a268711956e3bc3bcbbef0e07597a60b5ef52d0ed1fc314f433ee94968231fb633efad657d281258f12313220226824320875e5
6
+ metadata.gz: 5827bf20fcbb6aa5380e1cb68a876629235b1abbda98b74b5d562a483f812a6b7f9579f2b581803a1f5efacccb479bd651aae08bbb863ab40201c5af73f6b995
7
+ data.tar.gz: af772cae9ae42e41c6f1b99a2757713a18236107ac79f97d26ca3709e1618c6956ad993900897e59ff30fd7904ec53ee35d7d98cdcd8aa1df126415b617e16f2
@@ -0,0 +1,12 @@
1
+ 2.5.1
2
+ ----
3
+
4
+ * Get rid of most memoizations in favor of eager computations.
5
+
6
+ 2.5.0
7
+ -----
8
+
9
+ * Add `CHANGELOG.md`.
10
+ * Fix some deprecations and warnings.
11
+ * Support Rails 6 and Ruby 2.6.
12
+ * Cache conversion table in JSON file for first load performance.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "measured/base"
2
3
 
3
4
  require "measured/units/length"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Measured::Arithmetic
2
3
  def +(other)
3
4
  arithmetic_operation(other, :+)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "forwardable"
2
3
  require "measured/version"
3
4
  require "active_support/all"
@@ -23,10 +24,9 @@ module Measured
23
24
 
24
25
  def method_missing(method, *args)
25
26
  class_name = "Measured::#{ method }"
27
+ klass = class_name.safe_constantize
26
28
 
27
- if Measurable.subclasses.map(&:to_s).include?(class_name)
28
- klass = class_name.constantize
29
-
29
+ if klass && klass < Measurable
30
30
  Measured.define_singleton_method(method) do |value, unit|
31
31
  klass.new(value, unit)
32
32
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Measured::Cache
2
3
  class Json
3
4
  attr_reader :filename, :path
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Measured::Cache::JsonWriter
2
3
  def write(table)
3
4
  File.open(@path, "w") do |f|
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Measured::Cache
2
3
  class Null
3
4
  def exist?
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class Measured::ConversionTableBuilder
2
3
  attr_reader :units
3
4
 
@@ -87,5 +88,4 @@ class Measured::ConversionTableBuilder
87
88
 
88
89
  nil
89
90
  end
90
-
91
91
  end
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  class Measured::Measurable < Numeric
2
- DEFAULT_FORMAT_STRING = '%.2<value>f %<unit>s'
3
+ DEFAULT_FORMAT_STRING = "%.2<value>f %<unit>s"
3
4
 
4
5
  include Measured::Arithmetic
5
6
 
@@ -19,6 +20,18 @@ class Measured::Measurable < Numeric
19
20
  else
20
21
  BigDecimal(value)
21
22
  end
23
+
24
+ @value_string = begin
25
+ str = case value
26
+ when Rational
27
+ value.denominator == 1 ? value.numerator.to_s : value.to_f.to_s
28
+ when BigDecimal
29
+ value.to_s("F")
30
+ else
31
+ value.to_f.to_s
32
+ end
33
+ str.gsub(/\.0*\Z/, "")
34
+ end.freeze
22
35
  end
23
36
 
24
37
  def convert_to(new_unit)
@@ -39,18 +52,16 @@ class Measured::Measurable < Numeric
39
52
  end
40
53
 
41
54
  def to_s
42
- @to_s ||= "#{value_string} #{unit.name}"
55
+ "#{@value_string} #{unit.name}"
43
56
  end
44
57
 
45
58
  def humanize
46
- @humanize ||= begin
47
- unit_string = value == 1 ? unit.name : ActiveSupport::Inflector.pluralize(unit.name)
48
- "#{value_string} #{unit_string}"
49
- end
59
+ unit_string = value == 1 ? unit.name : ActiveSupport::Inflector.pluralize(unit.name)
60
+ "#{@value_string} #{unit_string}"
50
61
  end
51
62
 
52
63
  def inspect
53
- @inspect ||= "#<#{self.class}: #{value_string} #{unit.inspect}>"
64
+ "#<#{self.class}: #{@value_string} #{unit.inspect}>"
54
65
  end
55
66
 
56
67
  def <=>(other)
@@ -86,18 +97,4 @@ class Measured::Measurable < Numeric
86
97
  def unit_from_unit_or_name!(value)
87
98
  value.is_a?(Measured::Unit) ? value : self.class.unit_system.unit_for!(value)
88
99
  end
89
-
90
- def value_string
91
- @value_string ||= begin
92
- str = case value
93
- when Rational
94
- value.denominator == 1 ? value.numerator.to_s : value.to_f.to_s
95
- when BigDecimal
96
- value.to_s("F")
97
- else
98
- value.to_f.to_s
99
- end
100
- str.gsub(/\.0*\Z/, "")
101
- end
102
- end
103
100
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Measured::Parser
2
3
  extend self
3
4
 
@@ -1,12 +1,16 @@
1
+ # frozen_string_literal: true
1
2
  class Measured::Unit
2
3
  include Comparable
3
4
 
4
- attr_reader :name, :aliases, :conversion_amount, :conversion_unit, :unit_system
5
+ attr_reader :name, :names, :aliases, :conversion_amount, :conversion_unit, :unit_system, :inverse_conversion_amount
5
6
 
6
7
  def initialize(name, aliases: [], value: nil, unit_system: nil)
7
8
  @name = name.to_s.freeze
8
9
  @aliases = aliases.map(&:to_s).map(&:freeze).freeze
10
+ @names = ([@name] + @aliases).sort!.freeze
9
11
  @conversion_amount, @conversion_unit = parse_value(value) if value
12
+ @inverse_conversion_amount = (1 / conversion_amount if conversion_amount)
13
+ @conversion_string = ("#{conversion_amount} #{conversion_unit}" if conversion_amount || conversion_unit)
10
14
  @unit_system = unit_system
11
15
  end
12
16
 
@@ -14,30 +18,24 @@ class Measured::Unit
14
18
  self.class.new(
15
19
  name,
16
20
  aliases: aliases,
17
- value: conversion_string,
21
+ value: @conversion_string,
18
22
  unit_system: unit_system
19
23
  )
20
24
  end
21
25
 
22
- def names
23
- @names ||= ([name] + aliases).sort!.freeze
24
- end
25
-
26
26
  def to_s
27
- @to_s ||= if conversion_string
28
- "#{name} (#{conversion_string})".freeze
27
+ if @conversion_string
28
+ "#{name} (#{@conversion_string})".freeze
29
29
  else
30
30
  name
31
31
  end
32
32
  end
33
33
 
34
34
  def inspect
35
- @inspect ||= begin
36
- pieces = [name]
37
- pieces << "(#{aliases.join(", ")})" if aliases.any?
38
- pieces << conversion_string if conversion_string
39
- "#<#{self.class.name}: #{pieces.join(" ")}>".freeze
40
- end
35
+ pieces = [name]
36
+ pieces << "(#{aliases.join(", ")})" if aliases.any?
37
+ pieces << @conversion_string if @conversion_string
38
+ "#<#{self.class.name}: #{pieces.join(" ")}>".freeze
41
39
  end
42
40
 
43
41
  def <=>(other)
@@ -53,16 +51,8 @@ class Measured::Unit
53
51
  end
54
52
  end
55
53
 
56
- def inverse_conversion_amount
57
- @inverse_conversion_amount ||= 1 / conversion_amount if conversion_amount
58
- end
59
-
60
54
  private
61
55
 
62
- def conversion_string
63
- @conversion_string ||= ("#{conversion_amount} #{conversion_unit}" if conversion_amount || conversion_unit)
64
- end
65
-
66
56
  def parse_value(tokens)
67
57
  case tokens
68
58
  when String
@@ -1,17 +1,16 @@
1
+ # frozen_string_literal: true
1
2
  class Measured::UnitSystem
2
- attr_reader :units
3
+ attr_reader :units, :unit_names, :unit_names_with_aliases
3
4
 
4
5
  def initialize(units, cache: nil)
5
6
  @units = units.map { |unit| unit.with_unit_system(self) }
7
+ @unit_names = @units.map(&:name).sort.freeze
8
+ @unit_names_with_aliases = @units.flat_map(&:names).sort.freeze
9
+ @unit_name_to_unit = @units.each_with_object({}) do |unit, hash|
10
+ unit.names.each { |name| hash[name.to_s] = unit }
11
+ end
6
12
  @conversion_table_builder = Measured::ConversionTableBuilder.new(@units, cache: cache)
7
- end
8
-
9
- def unit_names_with_aliases
10
- @unit_names_with_aliases ||= @units.flat_map(&:names).sort
11
- end
12
-
13
- def unit_names
14
- @unit_names ||= @units.map(&:name).sort
13
+ @conversion_table = @conversion_table_builder.to_h.freeze
15
14
  end
16
15
 
17
16
  def unit_or_alias?(name)
@@ -51,14 +50,5 @@ class Measured::UnitSystem
51
50
 
52
51
  protected
53
52
 
54
- def conversion_table
55
- @conversion_table ||= @conversion_table_builder.to_h
56
- end
57
-
58
- def unit_name_to_unit
59
- @unit_name_to_unit ||= @units.inject({}) do |hash, unit|
60
- unit.names.each { |name| hash[name.to_s] = unit }
61
- hash
62
- end
63
- end
53
+ attr_reader :unit_name_to_unit, :conversion_table
64
54
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class Measured::UnitSystemBuilder
2
3
  def initialize
3
4
  @units = []
@@ -45,8 +46,8 @@ class Measured::UnitSystemBuilder
45
46
  ["P", "peta", 15],
46
47
  ["E", "exa", 18],
47
48
  ["Z", "zetta", 21],
48
- ["Y", "yotta", 24]
49
- ]
49
+ ["Y", "yotta", 24],
50
+ ].map(&:freeze).freeze
50
51
 
51
52
  def build_si_units(name, aliases: [], value: nil)
52
53
  si_units = [build_unit(name, aliases: aliases, value: value)]
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  Measured::Length = Measured.build do
2
3
  si_unit :m, aliases: [:meter, :metre, :meters, :metres]
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  Measured::Volume = Measured.build do
2
3
  si_unit :l, aliases: [:liter, :litre, :liters, :litres]
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  Measured::Weight = Measured.build do
2
3
  si_unit :g, aliases: [:gram, :grams]
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Measured
2
- VERSION = "2.5.0"
3
+ VERSION = "2.5.1"
3
4
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::ArithmeticTest < ActiveSupport::TestCase
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::Cache::JsonTest < ActiveSupport::TestCase
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::Cache::JsonWriterTest < ActiveSupport::TestCase
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::Cache::NullTest < ActiveSupport::TestCase
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  # In general we do not want to expose the inner workings of the caching and unit systems as part of the API.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::ConversionTableBuilderTest < ActiveSupport::TestCase
@@ -1,7 +1,7 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::MeasurableTest < ActiveSupport::TestCase
4
-
5
5
  setup do
6
6
  @arcane = Magic.unit_system.unit_for!(:arcane)
7
7
  @fireball = Magic.unit_system.unit_for!(:fireball)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::ParserTest < ActiveSupport::TestCase
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class AlwaysTrueCache
2
3
  def exist?
3
4
  true
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  Magic = Measured.build do
2
3
  unit :magic_missile, aliases: [:magic_missiles, "magic missile"]
3
4
  unit :fireball, value: "2/3 magic_missile", aliases: [:fire, :fireballs]
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Extract the subclasses that exist early on because other classes will get added by tests
2
3
  # later on in execution and in an unpredictable order.
3
4
  class ActiveSupport::TestCase
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "pry" unless ENV["CI"]
2
3
  require "measured"
3
4
  require "minitest/reporters"
@@ -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
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::UnitSystemTest < ActiveSupport::TestCase
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "test_helper"
2
3
 
3
4
  class Measured::UnitTest < ActiveSupport::TestCase
@@ -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,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: measured
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin McPhillips
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-05-21 00:00:00.000000000 Z
13
+ date: 2019-07-12 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -106,6 +106,7 @@ extra_rdoc_files: []
106
106
  files:
107
107
  - ".gitignore"
108
108
  - ".travis.yml"
109
+ - CHANGELOG.md
109
110
  - Gemfile
110
111
  - LICENSE
111
112
  - README.md